question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unable to use custom JsonFormat.Printer for ProtobufResponseConverterFunction

See original GitHub issue

Hello, we’re trying to use in a custom com.google.protobuf.util.JsonFormat.Printer for the ProtobufResponseConverterFunction , which we are using to convert the HttpResult from our endpoint into JSON

We’re doing this by passing in a custom instance of the converter function like so:

serverBuilder.annotatedService(myService, ProtobufResponseConverterFunction(JsonFormat.printer().includingDefaultValueFields()))) 

However, the custom Printer isn’t being used. It looks like a new converter is being instantiated along the way, which results in the Printer passed in to be ignored

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:1
  • Comments:20 (20 by maintainers)

github_iconTop GitHub Comments

2reactions
ikhooncommented, Jul 1, 2022

Let’s say we have the following annotated service:

class MyService {
  @ProduceJson
  fun flowProtobufJson(...): Flow<MyProtobuf> {
      ...
  }

}

Server.buider()
      .annotatedService()
      .responseConverters(MyProtobufResponseConverter())
      .build(MyService())

We need two 2 response converters to completely convert Flow<MyProtobuf> into a JSON response. First, MyProtobufResponseConverter will be used to convert each MyProtobuf into a JSON object. Next, FlowResponseConverterFunction should be chosen to collect the JSON objects and convert them into a JSON array.

Currently, we provide two APIs for a custom response converter.

  • ResponseConverterFunction defines how to convert an object.
  • ResponseConverterFunctionProvider defines how to create a ResponseConverterFunction via SPI.

The downside of the APIs is that they don’t tell a ResponseConverterFunction is a primitive converter or a delegating ResponseConverterFunction. It is difficult to prioritize between them. So we’d like to change our API to show their explicit behavior. Note: As the API is @UnstableApi, we can still make a breaking change. 😅

Proposal:

  • Split the original ResponseConverterFunctionProvider to two providers. DelegatingResponseConverterFunctionProvider requires a delegate to complete to convert a response like FlowResponseConverterFunction and the new ResponseConverterFunctionProvider does not take any parameters.
  • Add ResponseConverterFunctionProvider that create a primitive ResponseConverterFunction which converters an object to an HttpResponse without depending on other ResponseConverterFunctions.
  • A response converter created from DelegatingResponseConverterFunctionProvider has higher priority than primitive converters. Because it needs primitive converters to create a delegating response converter.
public interface ResponseConverterFunctionProvider {
    @Nullable
    ResponseConverterFunction newResponseConverterFunction();
}

public interface DelegatingResponseConverterFunctionProvider {

    @Nullable
    ResponseConverterFunction createResponseConverterFunction(
         Type responseType,
         ResponseConverterFunction responseConverter);
}
2reactions
jrhee17commented, Jun 22, 2022

Just for clarification:

Change the ResponseConverterFunctionProvider to use the configured responseConverterFunctions or to be applied after the responseConverterFunctions

By this, I think we mean that we will define the behavior of armeria’s default ResponseConverterFunctionProvider implementation such that it returns a function:

  1. Try to apply the passed responseConverterFunction
  2. If the passed responseConverterFunction falls through, the ResponseConverterFunctionProvider will try to apply its own ResponseConverterFunction

so I guess the PR would look roughly like follows (the same would be applied to ScalaPbResponseConverterFunctionProvider):

public final class ProtobufResponseConverterFunctionProvider implements ResponseConverterFunctionProvider {
...
    public ResponseConverterFunction createResponseConverterFunction(
            Type returnType,
            ResponseConverterFunction responseConverter) {
        if (isSupportedType(returnType)) {
            return new responseConverter.orElse(ProtobufResponseConverterFunction);
        }
...

I wanted to make sure I also understood @minwoox 's comments correctly 😅

Read more comments on GitHub >

github_iconTop Results From Across the Web

JsonFormat.Printer serializes custom options, but ... - GitHub
JsonFormat.Printer serializes custom options, but JsonFormat.Parser fails to deserialize them #7223.
Read more >
JsonFormat.Printer - Google Developers
A Printer converts protobuf message to JSON format. ... Printer that is configured to use the original proto field names as defined in...
Read more >
JsonFormat.printer().print() doesn't accept my Message
If I want to apply JsonFormat.printer().print() to one of my Message, the project doesn't compile and the method is underlined in red: ...
Read more >
Class JsonFormat.Printer | Java client library - Google Cloud
A Printer converts protobuf message to JSON format. ... Creates a new Printer that is configured to use the original proto field names...
Read more >
JsonFormat.Printer (Protocol Buffers [Util] 3.0.2 API) - javadoc.io
A Printer converts protobuf message to JSON format. ... Printer that is configured to use the original proto field names as defined in...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found