Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kotlin: javax.ws.rs.ProcessingException: RESTEASY003215: could not find writer for content-type application/json type #18792

Closed
GavinRay97 opened this issue Jul 19, 2021 · 7 comments
Labels
area/kotlin kind/bug Something isn't working

Comments

@GavinRay97
Copy link
Contributor

GavinRay97 commented Jul 19, 2021

Describe the bug

@ApplicationScoped
class ConfigManager {
    @ConfigProperty(name = "hasura.graphql.admin.secret")
    lateinit var hasuraAdminSecret: Optional<String>

    @ConfigProperty(name = "hasura.graphql.endpoint", defaultValue = "http://localhost:8080")
    lateinit var hasuraEndpoint: String
}

/*******************************************************/

interface HasuraAPI {
    @POST
    @Path("/v1/metadata")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    fun metadataRequest(payload: MetadataQueryPayload): ObjectNode // Jackson JSON object
}

@ApplicationScoped
class HasuraAPIClient {

    @Inject lateinit var configManager: ConfigManager

    val client: HasuraAPI by lazy {
        RestClientBuilder.newBuilder()
            .baseUri(URI(configManager.hasuraEndpoint))
            .build(HasuraAPI::class.java)
    }

    fun exportMetadata(): ObjectNode {
        val payload = MetadataQueryPayload(
            type = "export_metadata",
            args = ObjectMapper().createObjectNode()
        )
        return client.metadataRequest(payload)
    }
}

class MetadataQueryPayload(
    @JsonProperty("type") val type: String,
    @JsonProperty("args") val args: ObjectNode,
    @JsonProperty("version") val version: Int? = 2
)

/*******************************************************/

@QuarkusTest
internal class HasuraAPIClientTest {

    @Inject
    lateinit var client: HasuraAPIClient

    @Test
    fun `export metadata works`() {
        val response = client.exportMetadata()
        expect {
            that(response).isA<ObjectNode>()
            that(response["metadata"]["version"]).isA<Int>()
        }
    }
}

Expected behavior

This succeeds (or it tells me what I'm doing wrong in language so simple even I can understand it😅)

Actual behavior

Running Gradle on WSL...

INFO: Installed features: [cdi, config-yaml, jaxrs-client-reactive, kotlin, qute, rest-client, rest-client-mutiny, rest-client-reactive, rest-client-reactive-jackson, resteasy-reactive, resteasy-reactive-jackson, resteasy-reactive-qute, smallrye-context-propagation, smallrye-health, vertx]

RESTEASY004655: Unable to invoke request: javax.ws.rs.ProcessingException: RESTEASY003215: could not find writer for content-type application/json type: org.hasura.MetadataQueryPayload
javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: javax.ws.rs.ProcessingException: RESTEASY003215: could not find writer for content-type application/json type: org.hasura.MetadataQueryPayload
	at org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.invoke(ManualClosingApacheHttpClient43Engine.java:299)
	at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:494)
	at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:152)
	at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:115)
	at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)
	at jdk.proxy6/jdk.proxy6.$Proxy65.metadataRequest(Unknown Source)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
	at 
org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
	at java.base/java.lang.Thread.run(Thread.java:831)


Caused by: javax.ws.rs.ProcessingException: RESTEASY003215: could not find writer for content-type application/json type: org.hasura.MetadataQueryPayload
	at org.jboss.resteasy.core.interception.jaxrs.ClientWriterInterceptorContext.throwWriterNotFoundException(ClientWriterInterceptorContext.java:50)
	at org.jboss.resteasy.core.interception.jaxrs.AbstractWriterInterceptorContext.getWriter(AbstractWriterInterceptorContext.java:302)
	at org.jboss.resteasy.core.interception.jaxrs.AbstractWriterInterceptorContext.syncProceed(AbstractWriterInterceptorContext.java:240)
	at org.jboss.resteasy.core.interception.jaxrs.AbstractWriterInterceptorContext.proceed(AbstractWriterInterceptorContext.java:224)
	at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.writeRequestBody(ClientInvocation.java:446)
	at org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.writeRequestBodyToOutputStream(ManualClosingApacheHttpClient43Engine.java:603)
	at org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.buildEntity(ManualClosingApacheHttpClient43Engine.java:562)
	at org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.loadHttpMethod(ManualClosingApacheHttpClient43Engine.java:467)
	at org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.invoke(ManualClosingApacheHttpClient43Engine.java:277)
	... 106 more

HasuraAPIClientTest > export metadata works() FAILED
    javax.ws.rs.ProcessingException at HasuraAPIClientTest.kt:18
        Caused by: javax.ws.rs.ProcessingException at HasuraAPIClientTest.kt:18
Jul 18, 2021 10:52:58 PM io.quarkus.bootstrap.runner.Timing printStopTime
INFO: Quarkus stopped in 0.023s
Jul 18, 2021 10:52:58 PM org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine finalize
WARN: RESTEASY004687: Closing a class org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine instance for you. Please close clients yourself.

How to Reproduce?

Code above is set up with Graal 21.3.0-dev JDK16 and the following Gradle deps, from the latest (2.1.0-CR1) release of Quarkus:

plugins {
    val kotlinVersion = "1.5.20"
    kotlin("jvm") version kotlinVersion
    kotlin("kapt") version kotlinVersion
    kotlin("plugin.allopen") version kotlinVersion
    id("org.jlleitschuh.gradle.ktlint") version "10.1.0"
    id("io.quarkus")
}

repositories {
    mavenCentral()
    mavenLocal()
}

val quarkusPlatformGroupId: String by project
val quarkusPlatformArtifactId: String by project
val quarkusPlatformVersion: String by project

dependencies {
    implementation(enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}"))

    implementation("io.quarkus:quarkus-arc")
    implementation("io.quarkus:quarkus-config-yaml")
    implementation("io.quarkus:quarkus-container-image-docker")
    implementation("io.quarkus:quarkus-jaxrs-client-reactive")
    implementation("io.quarkus:quarkus-kotlin")
    implementation("io.quarkus:quarkus-mutiny")
    implementation("io.quarkus:quarkus-rest-client-mutiny")
    implementation("io.quarkus:quarkus-rest-client-reactive")
    implementation("io.quarkus:quarkus-rest-client-reactive-jackson")
    implementation("io.quarkus:quarkus-resteasy-reactive")
    implementation("io.quarkus:quarkus-resteasy-reactive-jackson")
    implementation("io.quarkus:quarkus-resteasy-reactive-qute")
    implementation("io.quarkus:quarkus-smallrye-health")
    implementation("io.quarkus:quarkus-vertx")

    implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.0")
    implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.12.3")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")

    implementation("io.vertx:vertx-lang-kotlin:4.1.1")
    implementation("io.vertx:vertx-lang-kotlin-coroutines:4.1.1")

    implementation("org.rauschig:jarchivelib:1.1.0")

    // Test Dependencies
    testImplementation("io.quarkus:quarkus-junit5")
    testImplementation("io.rest-assured:rest-assured")
    testImplementation("io.rest-assured:kotlin-extensions")

    testImplementation(platform("io.strikt:strikt-bom:0.31.0"))
    testImplementation("io.strikt:strikt-core")
    testImplementation("io.strikt:strikt-jvm")

    testImplementation("org.testcontainers:testcontainers:1.15.3")
    testImplementation("org.testcontainers:junit-jupiter:1.15.3")
}

java {
    sourceCompatibility = JavaVersion.VERSION_16
    targetCompatibility = JavaVersion.VERSION_16
}

allOpen {
    annotation("javax.ws.rs.Path")
    annotation("javax.enterprise.context.ApplicationScoped")
    annotation("io.quarkus.test.junit.QuarkusTest")
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
    kotlinOptions.jvmTarget = JavaVersion.VERSION_16.toString()
    kotlinOptions.javaParameters = trwue
    kotlinOptions.freeCompilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn")
}

Output of uname -a or ver

No response

Output of java -version

No response

GraalVM version (if different from Java)

No response

Quarkus version or git rev

No response

Build tool (ie. output of mvnw --version or gradlew --version)

No response

Additional information

No response

@GavinRay97 GavinRay97 added the kind/bug Something isn't working label Jul 19, 2021
@quarkus-bot
Copy link

quarkus-bot bot commented Jul 19, 2021

/cc @evanchooly

@geoand
Copy link
Contributor

geoand commented Jul 21, 2021

It seems like you are mixing rest-client and rest-client-reactive. Does the same thing happen if you remove the rest-client?

@GavinRay97
Copy link
Contributor Author

Ah -- is the:

implementation("io.quarkus:quarkus-rest-client-mutiny")

Pulling in rest-client as well? 😬
Will check something, one moment

@geoand
Copy link
Contributor

geoand commented Jul 21, 2021

Ah -- is the:

implementation("io.quarkus:quarkus-rest-client-mutiny")

Pulling in rest-client as well?

Yup

@GavinRay97
Copy link
Contributor Author

Oh man, big no-no crossing the streams like that 🙈
I thought it was pulling in generic mutiny operators for either of the rest-client/rest-client-reactive implementations.

Whoops.

Let me remove and test again, thank you for that piece of info 🤦 🙏

+--- io.quarkus:quarkus-rest-client-mutiny -> 2.1.0.CR1
|    +--- io.quarkus:quarkus-rest-client:2.1.0.CR1
|    |    +--- io.quarkus:quarkus-core:2.1.0.CR1 (*)
|    |    +--- io.quarkus:quarkus-arc:2.1.0.CR1 (*)
|    |    +--- io.quarkus:quarkus-resteasy-common:2.1.0.CR1
|    |    |    +--- io.quarkus:quarkus-core:2.1.0.CR1 (*)
|    |    |    +--- org.jboss.resteasy:resteasy-core:4.7.0.Final
|    |    |    |    +--- org.jboss.logging:jboss-logging:3.4.2.Final
|    |    |    |    +--- org.jboss.spec.javax.ws.rs:jboss-jaxrs-api_2.1_spec:2.0.1.Final
|    |    |    |    +--- org.jboss.spec.javax.xml.bind:jboss-jaxb-api_2.3_spec:2.0.0.Final
|    |    |    |    +--- org.jboss.resteasy:resteasy-core-spi:4.7.0.Final
|    |    |    |    |    +--- org.jboss.logging:jboss-logging:3.4.2.Final
|    |    |    |    |    +--- org.jboss.spec.javax.ws.rs:jboss-jaxrs-api_2.1_spec:2.0.1.Final
|    |    |    |    |    +--- org.jboss.spec.javax.xml.bind:jboss-jaxb-api_2.3_spec:2.0.0.Final
|    |    |    |    |    +--- org.reactivestreams:reactive-streams:1.0.3
|    |    |    |    |    \--- jakarta.validation:jakarta.validation-api:2.0.2
|    |    |    |    +--- org.reactivestreams:reactive-streams:1.0.3
|    |    |    |    +--- jakarta.activation:jakarta.activation-api:1.2.1
|    |    |    |    +--- jakarta.validation:jakarta.validation-api:2.0.2
|    |    |    |    +--- com.ibm.async:asyncutil:0.1.0
|    |    |    |    \--- io.smallrye.config:smallrye-config:2.3.0 -> 2.4.2 (*)
|    |    |    +--- io.quarkus:quarkus-arc:2.1.0.CR1 (*)
|    |    |    \--- com.sun.activation:jakarta.activation:1.2.1
|    |    +--- io.quarkus:quarkus-apache-httpclient:2.1.0.CR1
|    |    |    +--- io.quarkus:quarkus-arc:2.1.0.CR1 (*)
|    |    |    +--- org.apache.httpcomponents:httpclient:4.5.13
|    |    |    |    +--- org.apache.httpcomponents:httpcore:4.4.13 -> 4.4.14
|    |    |    |    +--- commons-logging:commons-logging:1.2
|    |    |    |    \--- commons-codec:commons-codec:1.11 -> 1.15
|    |    |    \--- org.jboss.logging:commons-logging-jboss-logging:1.0.0.Final
|    |    |         \--- org.jboss.logging:jboss-logging:3.3.1.Final -> 3.4.2.Final
|    |    +--- org.jboss.resteasy:resteasy-client-microprofile:4.7.0.Final
|    |    |    \--- org.jboss.resteasy:resteasy-client-microprofile-base:4.7.0.Final
|    |    |         +--- org.jboss.resteasy:resteasy-client:4.7.0.Final
|    |    |         |    +--- org.jboss.resteasy:resteasy-client-api:4.7.0.Final
|    |    |         |    |    +--- org.jboss.resteasy:resteasy-core-spi:4.7.0.Final (*)
|    |    |         |    |    +--- org.jboss.logging:jboss-logging:3.4.2.Final
|    |    |         |    |    \--- org.jboss.spec.javax.ws.rs:jboss-jaxrs-api_2.1_spec:2.0.1.Final
|    |    |         |    +--- org.jboss.resteasy:resteasy-core-spi:4.7.0.Final (*)
|    |    |         |    +--- org.jboss.resteasy:resteasy-core:4.7.0.Final (*)
|    |    |         |    +--- org.jboss.logging:jboss-logging:3.4.2.Final
|    |    |         |    +--- org.apache.httpcomponents:httpclient:4.5.13 (*)
|    |    |         |    +--- commons-codec:commons-codec:1.15
|    |    |         |    +--- commons-io:commons-io:2.9.0 -> 2.11.0
|    |    |         |    +--- org.jboss.spec.javax.ws.rs:jboss-jaxrs-api_2.1_spec:2.0.1.Final
|    |    |         |    \--- org.reactivestreams:reactive-streams:1.0.3
|    |    |         +--- org.jboss.resteasy:resteasy-cdi:4.7.0.Final
|    |    |         |    +--- org.jboss.spec.javax.ws.rs:jboss-jaxrs-api_2.1_spec:2.0.1.Final
|    |    |         |    +--- org.jboss.spec.javax.interceptor:jboss-interceptors-api_1.2_spec:2.0.0.Final
|    |    |         |    +--- jakarta.validation:jakarta.validation-api:2.0.2
|    |    |         |    +--- org.jboss.resteasy:resteasy-core-spi:4.7.0.Final (*)
|    |    |         |    +--- org.jboss.resteasy:resteasy-core:4.7.0.Final (*)
|    |    |         |    +--- org.jboss.logging:jboss-logging:3.4.2.Final
|    |    |         |    \--- org.jboss.weld:weld-api:3.1.SP4
|    |    |         |         \--- jakarta.enterprise:jakarta.enterprise.cdi-api:2.0.2 (*)
|    |    |         \--- org.eclipse.microprofile.rest.client:microprofile-rest-client-api:2.0
|    |    +--- jakarta.interceptor:jakarta.interceptor-api:1.2.5 (*)
|    |    +--- org.apache.httpcomponents:httpasyncclient:4.1.4
|    |    |    +--- org.apache.httpcomponents:httpcore:4.4.10 -> 4.4.14
|    |    |    +--- org.apache.httpcomponents:httpcore-nio:4.4.10 -> 4.4.14
|    |    |    |    \--- org.apache.httpcomponents:httpcore:4.4.14
|    |    |    \--- org.apache.httpcomponents:httpclient:4.5.6 -> 4.5.13 (*)
|    |    \--- org.jboss.logging:commons-logging-jboss-logging:1.0.0.Final (*)
|    \--- io.quarkus:quarkus-resteasy-mutiny-common:2.1.0.CR1
|         +--- io.quarkus:quarkus-resteasy-common:2.1.0.CR1 (*)
|         +--- io.quarkus:quarkus-mutiny:2.1.0.CR1 (*)
|         +--- org.jboss.resteasy:resteasy-client:4.7.0.Final (*)
|         \--- io.quarkus:quarkus-apache-httpclient:2.1.0.CR1 (*)

@GavinRay97
Copy link
Contributor Author

GavinRay97 commented Jul 21, 2021

@geoand Yeahhh, that did the trick. Closing -- Thanks once again friend. 🤦

Sidenote: Would it be worth putting logic in the conflicting extensions to check classpath for restXXX/restXXX-reactive and print out a warning if they both exist?

@geoand
Copy link
Contributor

geoand commented Jul 21, 2021

Glad to hear it.

Yeah, I was thinking of the same thing. I'll open a draft and see it how it goes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/kotlin kind/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants