0

I am trying to unmarshal java objects to xml in Spring integration using UnmarshallingTransformer but I am getting an error that the payload is not created. This is my code :


@Bean
    public Marshaller jaxbMarshaller() {
        Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
        jaxb2Marshaller.setClassesToBeBound(TargetedClass.class);

        return jaxb2Marshaller;
    }

@Bean
    public IntegrationFlow posting() {


        try {

            return IntegrationFlows.from(Http.inboundGateway("/foo")
                            .requestMapping(m -> m.methods(HttpMethod.POST)
                                    
                            ).errorChannel("error.input")
                    )

                    .transform(Transformers.objectToString())

                    .enrichHeaders(h -> h.headerExpression())
                    .transform(httpcallFunc())
                    .transform(new UnmarshallingTransformer((Unmarshaller) jaxbMarshaller()))

                    .get();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }

I am getting this error back.

org.springframework.messaging.MessagingException: failed to create Source for payload type [com.org.model.ClassName]
org.springframework.web.client.HttpServerErrorException$InternalServerError: 500 : "<Map><timestamp>2022-03-18T11:24:26.568+00:00</timestamp><status>500</status><error>Internal Server Error</error><path>/foo</path></Map>"

This occurs when I am trying to use the UnmarshallingTransformer.

Bash
  • 101
  • 11

1 Answers1

0

The UnmarshallingTransformer uses a DomSourceFactory by default. And its logic is like this:

        if (this.alwaysUseSourceFactory) {
            source = this.sourceFactory.createSource(payload);
        }
        else if (payload instanceof String) {
            source = new StringSource((String) payload);
        }
        else if (payload instanceof byte[]) {
            source = new StreamSource(new ByteArrayInputStream((byte[]) payload));
        }
        else if (payload instanceof File) {
            File file = (File) payload;
            inputStream = new FileInputStream(file);
            source = new StreamSource(inputStream, file.toURI().toASCIIString());
        }
        else if (payload instanceof Document) {
            source = new DOMSource((Document) payload);
        }
        else if (payload instanceof Source) {
            source = (Source) payload;
        }
        else {
            source = this.sourceFactory.createSource(payload);
        }

Since no one condition applies because of the default options and your custom type com.org.model.ClassName, it fails to the last else. The DomSourceFactory has a logic like this:

public Source createSource(Object payload) {
    Source source = null;
    if (payload instanceof Document) {
        source = createDomSourceForDocument((Document) payload);
    }
    else if (payload instanceof String) {
        source = createDomSourceForString((String) payload);
    }
    else if (payload instanceof File) {
        source = createDomSourceForFile((File) payload);
    }
    if (source == null) {
        throw new MessagingException("failed to create Source for payload type [" +
                payload.getClass().getName() + "]");
    }
    return source;
}

Which also does not satisfy your com.org.model.ClassName. Therefore an exception you see in your logs and so.

I'm not sure what is your expectations, but the type you produce from your httpcallFunc() is not what would be compatible with the UnmarshallingTransformer.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118