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

Unable to call getFileStatus, could not find writer for content-type application/json #102

Closed
Kernald opened this issue Jul 17, 2023 · 5 comments

Comments

@Kernald
Copy link

Kernald commented Jul 17, 2023

When using the Files API to call getFileStatus, I'm getting a RESTEASY004655 error:

Exception in thread "main" com.smartling.api.v2.client.exception.RestApiRuntimeException: http_status=500, method=getFileStatus, fileUri=video-feature/src/main/res/values/strings.xml/HEAD
        at com.smartling.api.v2.client.exception.RestApiExceptionHandler.createRestApiException(RestApiExceptionHandler.java:44)
        at com.smartling.api.v2.client.exception.RestApiExceptionHandler.createRestApiException(RestApiExceptionHandler.java:23)
        at com.smartling.api.v2.client.ExceptionDecoratorInvocationHandler.invoke(ExceptionDecoratorInvocationHandler.java:65)
        at com.sun.proxy.$Proxy14.authenticate(Unknown Source)
        at com.smartling.api.v2.client.auth.Authenticator.getAccessTokenInternal(Authenticator.java:121)
        at com.smartling.api.v2.client.auth.Authenticator.refreshOrRequestNewAccessToken(Authenticator.java:100)
        at com.smartling.api.v2.client.auth.Authenticator.getAccessToken(Authenticator.java:76)
        at com.smartling.api.v2.client.auth.BearerAuthSecretFilter.getTokenString(BearerAuthSecretFilter.java:28)
        at com.smartling.api.v2.client.auth.AbstractBearerAuthFilter.filter(AbstractBearerAuthFilter.java:19)
        at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:687)
        at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:489)
        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 com.sun.proxy.$Proxy21.getFileStatus(Unknown Source)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at com.smartling.api.v2.client.ExceptionDecoratorInvocationHandler.invoke(ExceptionDecoratorInvocationHandler.java:50)
        at com.sun.proxy.$Proxy22.getFileStatus(Unknown Source)
        at com.foo.bar.MainKt$downloadStrings$fileStatuses$1$1$1.invokeSuspend(Main.kt:226)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
        at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
        Suppressed: com.smartling.api.v2.client.exception.RestApiRuntimeException: http_status=500, method=getFileStatus, fileUri=prelaunch-screen-feature/src/main/res/values/strings.xml/HEAD
                ... 30 more
        Caused by: javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: javax.ws.rs.ProcessingException: RESTEASY003215: could not find writer for content-type application/json type: com.smartling.api.v2.authentication.pto.AuthenticationRequest
                at org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.invoke(ManualClosingApacheHttpClient43Engine.java:299)
                at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:492)
                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 com.sun.proxy.$Proxy13.authenticate(Unknown Source)
                at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
                at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.base/java.lang.reflect.Method.invoke(Method.java:566)
                at com.smartling.api.v2.client.ExceptionDecoratorInvocationHandler.invoke(ExceptionDecoratorInvocationHandler.java:50)
                ... 27 more

These are the dependencies I'm using (trying to follow the versions from the SDK and adding as runtime deps what I hoped would help - it didn't, more on this below):

    implementation("com.smartling.api:smartling-api-sdk:1.9.0")
    implementation("org.jetbrains.kotlinx:kotlinx-cli:0.3.5")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
    runtimeOnly("org.jboss.resteasy:resteasy-client:4.6.1.Final")
    runtimeOnly("org.glassfish.jersey.core:jersey-client:2.34")
    runtimeOnly("org.jboss.resteasy:resteasy-jackson2-provider:4.6.1.Final")
    runtimeOnly("org.jboss.resteasy:resteasy-multipart-provider:4.6.1.Final")
    runtimeOnly("com.fasterxml.jackson.core:jackson-databind:2.12.3")
    runtimeOnly("javax.xml.bind:jaxb-api:2.4.0-b180830.0359")
    runtimeOnly("org.jboss.resteasy:resteasy-jaxb-provider:4.6.1.Final")

This is how I create the API client:

  val clientFactory = ClientFactory()
  val clientConfiguration: ClientConfiguration = DefaultClientConfiguration.builder().build()
  val authenticationApi = AuthenticationApiFactory(clientFactory)
      .buildApi(clientConfiguration)
  val authenticator = Authenticator(userIdentifier, userSecret, authenticationApi)
  val bearerAuthSecretFilter = BearerAuthSecretFilter(authenticator)
  return FilesApiFactory(clientFactory).buildApi(bearerAuthSecretFilter, clientConfiguration)

And below, how it's used:

smartlingFilesApi.getFileStatus(
  projectId,
  "$relativePath/$key",
)

Without the additional runtime dependencies, the call to getFileStatus works, but then a call to downloadTranslatedFile fails trying to parse XML (as far as I can tell - it does dump the Android strings XML files as the request body in the exception details as well):

Exception in thread "main" com.smartling.api.v2.client.exception.RestApiRuntimeException: http_status=500, method=downloadTranslatedFile, fileUri=foo-bar/src/main/res/values$
        at com.smartling.api.v2.client.exception.RestApiExceptionHandler.createRestApiException(RestApiExceptionHandler.java:44)
        at com.smartling.api.v2.client.ExceptionDecoratorInvocationHandler.invoke(ExceptionDecoratorInvocationHandler.java:63)
        at com.sun.proxy.$Proxy22.downloadTranslatedFile(Unknown Source)
        at com.foo.bar.MainKt$downloadFiles$3$1$1.invokeSuspend(Main.kt:338)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
        at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)

[...]

        Caused by: javax.ws.rs.client.ResponseProcessingException: javax.ws.rs.ProcessingException: Error during response processing:
        type: java.io.InputStream
        genericType: class java.io.InputStream
        annotations: [
                @javax.ws.rs.GET()
                @javax.ws.rs.Path(value="/projects/{projectId}/locales/{localeId}/file")
                @javax.ws.rs.Produces(value={"*/*"})
        ]
        headers: [Cache-Control=no-cache,Connection=keep-alive,Content-Disposition=attachment; filename="foo-bar/src/main/res/values/strings.xml/HEAD";,Content-T$
        media type: application/xml;charset=UTF-8
        body: <?xml version="1.0" encoding="UTF-8"?> [here goes the whole XML file]
                at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.extractResult(ClientInvocation.java:201)
                at org.jboss.resteasy.client.jaxrs.internal.proxy.extractors.BodyEntityExtractor.extractEntity(BodyEntityExtractor.java:64)
                at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:154)
                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 com.sun.proxy.$Proxy21.downloadTranslatedFile(Unknown Source)
                at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
                at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.base/java.lang.reflect.Method.invoke(Method.java:566)
                at com.smartling.api.v2.client.ExceptionDecoratorInvocationHandler.invoke(ExceptionDecoratorInvocationHandler.java:50)
                ... 10 more

[...]

        Caused by: javax.ws.rs.ProcessingException: RESTEASY003145: Unable to find a MessageBodyReader of content-type application/xml;charset=UTF-8 and type class java.io.InputS$
                at org.jboss.resteasy.core.interception.jaxrs.ClientReaderInterceptorContext.throwReaderNotFound(ClientReaderInterceptorContext.java:47)
                at org.jboss.resteasy.core.interception.jaxrs.AbstractReaderInterceptorContext.getReader(AbstractReaderInterceptorContext.java:133)
                at org.jboss.resteasy.core.interception.jaxrs.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:75)
                at com.smartling.api.v2.client.unmarshal.RestApiResponseReaderInterceptor.aroundReadFrom(RestApiResponseReaderInterceptor.java:46)
                ... 25 more

This is the PTO passed to downloadTranslatedFile:

DownloadTranslationPTO(
            uri, // fileStatus.fileUri, with fileStatus being the response of getFileStatus above
            RetrievalType.PUBLISHED,
            true,
        )

I'm assuming I'm either missing some runtime dependencies or initialisation to add a JSON and/or XML parser to RESTEasy (I'm not familiar with that at all). Is there a set-up part that's not documented/that I missed?

@mahdi-canva
Copy link

Hey @rsukharnyk-smartling, could you please look into this or ask the right folks to do so and give us an update? thanks

@rsukharnyk-smartling
Copy link
Contributor

rsukharnyk-smartling commented Sep 4, 2023

Hey @mahdi-canva . I've informed Team about Your request. Hope issue will be solved soon. Suppose You'll be notified additionally about the fix.
Thanks.

@mahdi-canva
Copy link

Hey @rsukharnyk-smartling, just checking for any updates as we haven't heard back yet.

@dnetrebenko-smartling
Copy link
Contributor

Hey guys! I couldn't find any errors for your requests on the side of our services. Then I tried to reproduce the problem but couldn't. I've created an empty kotlin project in my ide, copy-pasted your list of the dependencies and your API initialization code. And it worked for me without any errors.
my code is below.

build.gradle.kts:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.8.10"
    application
}

group = "me.diman"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.smartling.api:smartling-api-sdk:1.9.0")
    implementation("org.jetbrains.kotlinx:kotlinx-cli:0.3.5")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
    runtimeOnly("org.jboss.resteasy:resteasy-client:4.6.1.Final")
    runtimeOnly("org.glassfish.jersey.core:jersey-client:2.34")
    runtimeOnly("org.jboss.resteasy:resteasy-jackson2-provider:4.6.1.Final")
    runtimeOnly("org.jboss.resteasy:resteasy-multipart-provider:4.6.1.Final")
    runtimeOnly("com.fasterxml.jackson.core:jackson-databind:2.12.3")
    runtimeOnly("javax.xml.bind:jaxb-api:2.4.0-b180830.0359")
    runtimeOnly("org.jboss.resteasy:resteasy-jaxb-provider:4.6.1.Final")
    testImplementation(kotlin("test"))
}

tasks.test {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

application {
    mainClass.set("MainKt")
}

Main.kt:

import com.smartling.api.files.v2.FilesApi
import com.smartling.api.files.v2.FilesApiFactory
import com.smartling.api.files.v2.pto.DownloadTranslationPTO
import com.smartling.api.files.v2.pto.RetrievalType
import com.smartling.api.v2.authentication.AuthenticationApiFactory
import com.smartling.api.v2.client.ClientConfiguration
import com.smartling.api.v2.client.ClientFactory
import com.smartling.api.v2.client.DefaultClientConfiguration
import com.smartling.api.v2.client.auth.Authenticator
import com.smartling.api.v2.client.auth.BearerAuthSecretFilter
import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.stream.Collectors

fun main(args: Array<String>) {
    println("---> Start")
    val projectId = "..."
    val userIdentifier = "..."
    val userSecret = "..."
    val fileUri = "android-plurals-2.xml"
    val localeId = "fr"

    val fileApi = createApi(userIdentifier, userSecret)
    println("---> Created API")
    val statusResponse = fileApi.getFileStatus(projectId, fileUri)
    println("---> FileStatus response: $statusResponse")

    val downloadTranslationPTO = DownloadTranslationPTO.builder()
        .fileUri(fileUri)
        .retrievalType(RetrievalType.PUBLISHED)
        .includeOriginalStrings(true)
        .build();

    val stream = fileApi.downloadTranslatedFile(projectId, localeId, downloadTranslationPTO)
    val downloadResponse: String = BufferedReader(InputStreamReader(stream))
        .lines().collect(Collectors.joining("\n"))
    println("---> Download response: $downloadResponse")
}

fun createApi(userIdentifier: String, userSecret: String): FilesApi {
    val clientFactory = ClientFactory()
    val clientConfiguration: ClientConfiguration = DefaultClientConfiguration.builder()
        .build()
    val authenticationApi = AuthenticationApiFactory(clientFactory)
        .buildApi(clientConfiguration)
    val authenticator = Authenticator(userIdentifier, userSecret, authenticationApi)
    val bearerAuthSecretFilter = BearerAuthSecretFilter(authenticator)
    return FilesApiFactory(clientFactory).buildApi(bearerAuthSecretFilter, clientConfiguration)
}

Output:

> Task :MainKt.main()
---> Start
---> Created API
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
---> FileStatus response: FileStatusResponse(created=Fri Sep 22 11:50:10 EEST 2023, lastUploaded=Fri Sep 22 11:50:10 EEST 2023, fileType=android, fileUri=android-plurals-2.xml, hasInstructions=false, items=[FileStatusItemPTO(localeId=de, authorizedStringCount=0, authorizedWordCount=0, completedStringCount=0, completedWordCount=0, excludedStringCount=0, excludedWordCount=0), FileStatusItemPTO(localeId=es, authorizedStringCount=0, authorizedWordCount=0, completedStringCount=0, completedWordCount=0, excludedStringCount=0, excludedWordCount=0), FileStatusItemPTO(localeId=fr, authorizedStringCount=4, authorizedWordCount=18, completedStringCount=0, completedWordCount=0, excludedStringCount=0, excludedWordCount=0), FileStatusItemPTO(localeId=it, authorizedStringCount=0, authorizedWordCount=0, completedStringCount=0, completedWordCount=0, excludedStringCount=0, excludedWordCount=0), FileStatusItemPTO(localeId=ru-RU, authorizedStringCount=0, authorizedWordCount=0, completedStringCount=0, completedWordCount=0, excludedStringCount=0, excludedWordCount=0)], parserVersion=5, totalCount=5, totalStringCount=4, totalWordCount=18, directives=null, namespace=null)
Disconnected from the target VM, address: 'localhost:54035', transport: 'socket'
Connected to the target VM, address: '127.0.0.1:53991', transport: 'socket'
---> Download response: <?xml version="1.0" encoding="UTF-8"?>
<resources>

    <string name="string_1">Android.xml plurals testing. Multi segment string.</string>

    <plurals name="plural_strings2">
        <item quantity="one">You have %1$s item in your cart.</item>
        <item quantity="other">You have %1$s items in your cart</item>
    </plurals>

    <plurals name="plural_strings3">
        <item quantity="one">You have one check-in here.</item>
        <item quantity="other">You have %1$d check-ins here.</item>
    </plurals>

    <plurals name="plural_strings4">
        <item quantity="one">Deleting %1$d file.</item>
        <item quantity="other">Deleting %1$d files.</item>
    </plurals>

</resources>

probably you have a dependencies conflict. it's not enough information to reproduce the issue. could you write the whole list of your dependencies and more information about your environment (java version, jdk version, kotlin version and so on)?

@Kernald
Copy link
Author

Kernald commented Oct 30, 2023

Hi!

Sorry for the noise here, it was indeed a dependency issues - namely, running this as a Gradle task, the runtime dependencies were lost at some point in the chain. We now have it working as intended :-)

@Kernald Kernald closed this as completed Oct 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants