armeria: Unable to use custom JsonFormat.Printer for ProtobufResponseConverterFunction
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
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 20 (20 by maintainers)
Commits related to this issue
- Add delegating response converter function provider (#4336) Potentially resolves issue [4301](https://github.com/line/armeria/issues/4301#issuecomment-1171966536) Motivation: Fix bug with Pro... — committed to line/armeria by resquivel-squareup 2 years ago
- Add delegating response converter function provider (#4336) Potentially resolves issue [4301](https://github.com/line/armeria/issues/4301#issuecomment-1171966536) Motivation: Fix bug with Pro... — committed to heowc/armeria by resquivel-squareup 2 years ago
Let’s say we have the following annotated service:
We need two 2 response converters to completely convert
Flow<MyProtobuf>into a JSON response. First,MyProtobufResponseConverterwill be used to convert eachMyProtobufinto a JSON object. Next,FlowResponseConverterFunctionshould be chosen to collect the JSON objects and convert them into a JSON array.Currently, we provide two APIs for a custom response converter.
ResponseConverterFunctiondefines how to convert an object.ResponseConverterFunctionProviderdefines how to create aResponseConverterFunctionvia SPI.The downside of the APIs is that they don’t tell a
ResponseConverterFunctionis a primitive converter or a delegatingResponseConverterFunction. 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:
ResponseConverterFunctionProviderto two providers.DelegatingResponseConverterFunctionProviderrequires a delegate to complete to convert a response likeFlowResponseConverterFunctionand the newResponseConverterFunctionProviderdoes not take any parameters.ResponseConverterFunctionProviderthat create a primitiveResponseConverterFunctionwhich converters an object to anHttpResponsewithout depending on otherResponseConverterFunctions.DelegatingResponseConverterFunctionProviderhas higher priority than primitive converters. Because it needs primitive converters to create a delegating response converter.Just for clarification:
By this, I think we mean that we will define the behavior of
armeria’s defaultResponseConverterFunctionProviderimplementation such that it returns a function:responseConverterFunctionresponseConverterFunctionfalls through, theResponseConverterFunctionProviderwill try to apply its ownResponseConverterFunctionso I guess the PR would look roughly like follows (the same would be applied to
ScalaPbResponseConverterFunctionProvider):I wanted to make sure I also understood @minwoox 's comments correctly 😅
Ah, I just meant I didn’t write a test case for the exact scenario you mentioned for
Flow<MyProtobuf>so I can’t confirm that it’s actually workingHad a chat with the team and we realized:
ResponseConverterFunctionProvider(found via SPI) uses theresponseConverterFunctions set via annotation, service builder and default ones.ResponseConverterFunctionProviderand others is not about which one is used beforehand.ResponseConverterFunctionProvideruses the configuredresponseConverterFunctions.So here’s what we need to do:
ResponseConverterFunctionProviders that Armeria provides to use the configuredresponseConverterFunctions or to be applied after theresponseConverterFunctionsResponseConverterFunctionthey want via setterProtobufResponseConverterFunctionProviderandScalaPbResponseConverterFunctionProvidershould be fixed to abide by the rule.ResponseConverterFunction.orElse(responseConverterFunction)for easy chaining.return responseConverter.orElse(new ProtobufResponseConverterFunction());hereResponseConverterFunctionProvider.createResponseConverterFunction(...)to inform theResponseConverterFunctions parameter.To be precise, I think
ResponseConverterFunctions should be applied in the following order:ResponseConverterFunctionServerBuilder.annotatedService()and equivalentResponseConverterFunctionsWill give it a shot 👍