2

We are returning an array of objects from a service (http outbound gateway) in json format and we need it serialized back into an array of objects/POJOS. First we tried simply serializing the POJO without any array lists by setting the XML configuration to

<int:json-to-object-transformer input-channel="testJsonToObjectChannel"
            output-channel="testChannel" type="com.that.service.service.test.ApplicationTestDomain" />

and had both the transformer and the http outbound gateway return the same object. However after converting it to an array of "ApplicationTestDomain" POJOs we are getting the error mentioned in the stack trace where it notably mentions

"No converter found capable of converting from type java.util.ArrayList<?> to type com.that.service.service.test.ApplicationTestDomain"

We also tried a simple array of strings and they were succesfully serialized and deserialzed as well, the issue only comes up when we try to serialize and deserialize an array of objects.

Any idea on what needs to be done so that can be resolved

The following is the service which returns the array list

@Service("applicationTestService")
public class ApplicationTestService {

    private static Logger logger = Logger.getLogger(ApplicationTestService.class);

    public ArrayList<ApplicationTestDomain> getTestThatData(Message<?> inMessage){
        ArrayList<ApplicationTestDomain> testData = new ArrayList<ApplicationTestDomain>();

        ApplicationTestDomain testDomain = new ApplicationTestDomain();
        testDomain.setId(1L);
        testDomain.setTotalPrice(100.00D);
        testDomain.setTotalTaxes(70.00D);
        testDomain.setTotalAll(70D);

        testData.add(testDomain);

        return testData;
    }

}

The following is the service which receives the array list

@MessageEndpoint("applicationDataTransformer")
public class ApplicationTransformer {

    public ApplicationResponse transformData(ArrayList<ApplicationTestDomain> response) {
        return new ApplicationResponse();
    }
}

The following is the xml configuration

<int-http:outbound-gateway request-channel="applicationConfigurationRequest" 
                           reply-channel="testJsonToObjectChannel"
                           url="http://localhost:8080/testapplication/services/application/testService"
                           http-method="GET"
                           expected-response-type="java.lang.String"/>


<int:json-to-object-transformer input-channel="testJsonToObjectChannel"
        output-channel="testChannel" type="java.util.ArrayList" />

<int:transformer input-channel="testChannel"
    ref="applicationDataTransformer"
    method="transformData"
    output-channel="applicationConfigurationResponse"/>         

The following is the exception stack trace

at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.messaging.MessageHandlingException: org.springframework.expression.AccessException: Problem invoking method: public com.that.domain.service.hotelavailability.HotelAvailabilityResponse com.that.transformer.service.ApplicationTransformer.transformData(java.util.ArrayList)
    at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:78)
    at org.springframework.integration.transformer.AbstractMessageProcessingTransformer.transform(AbstractMessageProcessingTransformer.java:64)
    at org.springframework.integration.transformer.MessageTransformingHandler.handleRequestMessage(MessageTransformingHandler.java:68)
    ... 83 more
Caused by: org.springframework.expression.AccessException: Problem invoking method: public com.that.domain.service.hotelavailability.HotelAvailabilityResponse com.that.transformer.service.ApplicationTransformer.transformData(java.util.ArrayList)
    at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:67)
    at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:122)
    at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:44)
    at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:258)
    at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:84)
    at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:114)
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:111)
    at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:159)
    at org.springframework.integration.util.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:268)
    at org.springframework.integration.util.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:142)
    at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:75)
    ... 85 more
Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.util.ArrayList<?> to type java.util.ArrayList<com.that.service.service.test.ApplicationTestDomain> for value '[{id=1, totalPrice=100.0, totalTaxes=70.0, totalAll=70.0}]'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type java.util.ArrayList<?> to type com.that.service.service.test.ApplicationTestDomain
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174)
    at org.springframework.integration.util.BeanFactoryTypeConverter.convertValue(BeanFactoryTypeConverter.java:123)
    at org.springframework.expression.spel.support.ReflectionHelper.convertArguments(ReflectionHelper.java:240)
    at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:57)
    ... 95 more
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type java.util.ArrayList<?> to type com.that.service.service.test.ApplicationTestDomain
    at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:291)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:177)
    at org.springframework.core.convert.support.CollectionToCollectionConverter.convert(CollectionToCollectionConverter.java:85)
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:35)
    ... 99 more

Regards, MilindaD

1 Answer 1

6

Your issues here that you just use raw java.util.ArrayList and you end up just with ArrayList<LinkedHashMap<String, Object>>, rather than ArrayList<LinkedHashMap<String, ApplicationTestDomain>>.

Try this trick:

type="com.that.service.service.test.ApplicationTestDomain[]"

The general stop here that we can't provide Class with generic specification.

But with that array trick there should automatic conversion from Array to Collection when Framework appies Message to arguments of your service method.

From other side <int-http:outbound-gateway> provides expected-response-type-expression, which can return ParameterizedTypeReference<?>.

Here is a trick how to let him know about your desired type:

<int:header-enricher>
        <int:header name="expectedResponseType">
            <int-groovy:script>
                <![CDATA[
                    new org.springframework.core.ParameterizedTypeReference<List<com.that.service.service.test.ApplicationTestDomain>>() {}
                ]]>
            </int-groovy:script>       
        </int:header>
</int:header-enricher>

<int-http:outbound-gateway request-channel="applicationConfigurationRequest" 
                       reply-channel="testJsonToObjectChannel"
                       url="http://localhost:8080/testapplication/services/application/testService"
                       http-method="GET"
                       expected-response-type-expression="headers.expectedResponseType"/>

Having this you allow to RestTemplate to convert response to the desired value using Jackson, of course. And from here there is no more reason to use <int:json-to-object-transformer>, because you already have your List of POJOs.

Sign up to request clarification or add additional context in comments.

3 Comments

Hi, this definitely solved my problem. However in the broader schemes of things is there a cleaner way to this without using ParameterizedTypeReference? And if the only way to accomplish this is by using it then rather than using a ParameterizedTypeReference in seperate header enricher element is it possible to at least specify the ParameterizedTypeReference seperately and reference it directly in the "expected-response-type-expression" attribute then
Yes, you can do as method reference. Something like this: expected-response-type-expression="T (org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandlerTests).testParameterizedTypeReference()". Where that method just does: return new ParameterizedTypeReference<List<String>>() {};: github.com/spring-projects/spring-integration/blob/master/… and its HttpOutboundWithinChainTests class
Hi, How would you set the expected type for a json to object converter as I have a json array that needs to be converted to a list of objects. How would you define a json-to-object converter element

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.