Generic Json To Object transformer - spring-integration

Is there any way to set the value of "type" attribute of a JsonToObject transformer dynamically ?
For ex, A message header will tell you the target Java Object to which incoming Json payload should be converted to.
Something like,
<int:json-to-object-transformer
input-channel="jsonTransformationChannel" type="headers['targetJavaObject']"
output-channel="payloadTransformationChannel" />
NOTE : "type" attribute does not support SpEL expressions.

Starting with version 3, the JTOT uses similar headers to the Spring AMQP JSON message converters. See JsonHeaders.
For a simple type, set the json__TypeId__ header to the fully qualified class name and do not configure a type.

Related

No MessageBodyWriter for Single

I'm trying to use resteasy-rxjava2 to provide an XML document using jaxb, within a vertx application (using a non-vertx legacy library we have). But I get:
Could not find MessageBodyWriter for response object of type:
org.jboss.resteasy.rxjava2.propagation.ContextPropagatorOnSingleAssemblyAction$ContextPropagatorSingle of media type:
application/xml;charset=UTF-8
From what I can tell, this comes down to the difference between a MessageBodyWriter and the AsyncResponseProvider that is in the resteasy-rxjava2 dependency for a Single (SingleProvider).
I have the following resteasy service definition
#GET
#Path(FdsnwsPaths.QUERY)
#Produces(MediaType.APPLICATION_XML)
#Stream
// CHECKSTYLE:OFF too many parameters
public Response getQuery(...)
How do I get resteasy to properly serve the data asynchrously, using the SingleProvider or otherwise.
The #Get method must return the Single explicitly or it doesn't work. (Can't use Response or Object). In my case, the Single contains the jaxb xml root element.
#GET
#Path(FdsnwsPaths.QUERY)
#Produces(MediaType.APPLICATION_XML)
#Stream
public Single<FDSNStationXML> getQuery(...)
Then, to make things more complicated, in order to handle specific exception types and map them to specific response status codes, I have to create a custom ExceptionMapper which creates the Response object I used to be able to create directly in the method. (in resteasy-vertx, I found no documentation on how to do this, but in my case, I am creating my own VertxRestEasyDeployment object so I can register the class of the ExceptionMapper(s) like this:
VertxResteasyDeployment deployment = new VertxResteasyDeployment();
deployment.getActualProviderClasses().addAll(providerClasses);
For reference, this is all being done with:
RestEasy 5.0.3.Final (including resteasy-rxjava2)
RxJava 2.2.20
Vertx 3.9.5

Header annotation with "." in header name, such as #Header("foo.bar"), doesn't map

I have a simple Spring Integration message endpoint with the signature:
#Transformer
String handleMessage(#Payload String payload, #Header("nerf") String nerf, #Header("foo.bar") String foobar) {
//...
}
The variable nerf always contains the header value it received from Kafka. The variable foobar is always null, despite the header named foo.bar existing in the inbound message.
This is a simple DSL-based flow coming straight off the Kafka binder.
It seems that any parameter with a name that contains the . character doesn't get mapped properly.
What am I doing wrong? Is the #Header(name) a SpEL expression?
It's designed that way; so you can extract property bar from a header named foo.
However, quoting it as Oleg suggested should work, but does not; we end up looking for header ''foo' with property bar'.
I have opened a GitHub issue.

How to transform a LinkedHashMap Payload to Object Payload in mule?

I want to transform a LinkedHashMap Payload to Object Payload in mule , i used the Byte Array to Object transformer but it dosent work for me , any idea guys ?
you can use dataweave to transform a payload of generic type (=java.util.Map) to a specific type (foo.bar.Type in the example):
%dw 1.0
%output application/java
---
payload as :object {
class: "foo.bar.Type"
}
You seem to mention specifically the Object type. A LinkedHashMap is already an instance of Object: every Java instances inherit from the root class Object.
If you want to transform your HashMap into a specific object such as JSON or a custom object such as com.mycompany.CompData, you have several possibilities depending on your use case:
use DataWeave as mentioned in other answers (require EE)
use a built-in transformer such as Object-to-JSON
implement your own Transformer by extending AbstractTransformer
Se the docs for details: https://docs.mulesoft.com/mule-user-guide/v/3.8/using-transformers
If you may be more specific as to what your use case is I'll gladly refine my answer ;)
You can use either dataweave or json to object transformer.

spring XD - http-client add application/json header

I've installed Spring XD in my PaaS environment and for legacy issue I'm stuck with version 1.0.0.M1. ( see reference doc).
My goal is to call a http rest API using the http-client module. My stream definition is:
http | httpclient --url='''<my_url>''' --http-method=POST --mappedRequestHeaders=HTTP_REQUEST_HEADERS | log --expression=#root
Unfortunately, since the http module only sends the payload to the httpclient, the httpclient returns a 415 error due to the absence of the content-type header.
Considering that I can neither add new modules nor modify existing ones (in such a version you can only reference to the spring repository), I would like to use a tranform module to inject the content-type header.
How can I achieve such a goal?
Many thanks for your help.
EDIT:
I just found that httpclient processor (link) supports headersExpression A SpEL expression used to derive the http headers map to use. However:
--headers-expression='{Content-Type:'application/json'}'
Gives the following parse exception:
org.springframework.expression.spel.SpelEvaluationException: EL1008E:
(pos 1): Property or field 'Content' cannot be found on object of type 'org.springframework.messaging.support.GenericMessage' - maybe not public?
See GH issue for more StackTrace.
First of all it isn't Spring XD any more. Spring Cloud Dataflow is different product and its behavior maybe not that which you had with Spring XD before.
Second: it is in version 1.0.0.RC1 already. So, consider to upgrade.
Now on the problem. Look:
headersExpression
A SpEL expression used to derive the http headers map to use.
So, this expression must return a Map and it is confirmed by the code:
if (properties.getHeadersExpression() != null) {
Map<?, ?> headersMap = properties.getHeadersExpression().getValue(message, Map.class);
Now let's take a look into the problem:
org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 1): Property or field 'Content' cannot be found on object of type 'org.springframework.messaging.support.GenericMessage' - maybe not public?
org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:224) ~[spring-expression-4.2.4.RELEASE.jar!/:4.2.4.RELEASE]
org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94) ~[spring-expression-4.2.4.RELEASE.jar!/:4.2.4.RELEASE]
org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:81) ~[spring-expression-4.2.4.RELEASE.jar!/:4.2.4.RELEASE]
org.springframework.expression.spel.ast.OpMinus.getValueInternal(OpMinus.java:98) ~[spring-expression-4.2.4.RELEASE.jar!/:4.2.4.RELEASE]
OpMinus is a root of cause. So, SpEL treats Content-Type expression as a minus operator.
Sad, of course, but the workaround is like wrapping the key into quotes as well:
--headers-expression={'Content-Type':'application/json'}

Mule Jaxb to object transforms to wrong object

I have an integration with some flows and JAXBcontext declared like this
<mulexml:jaxb-context name="JaxbContext" packageNames="se.razorlib.SystemAProduct:se.razorlib.SystemAPurchase:se.razorlib.SystemAOrder"/>
In one of my flows I transform XML to Purchase and in another XML to Order, which are very similar objects.
However, in the Order flow JAXB transforms my XML to PurchaseObject instead of OrderObject, which of course throws me an error:
The object transformed is of type: "SimpleDataType{type=se.razorlib.SystemAPurchase.Header, mimeType='*/*', encoding='null'}", but the expected return type is "SimpleDataType{type=se.razorlib.SystemAOrder.Header, mimeType='*/*', encoding='null'}"
This is my configuration, how can I force a tranfsformation to the "right" object?
<file:inbound-endpoint path="C:\temp\OrderfileIn" responseTimeout="10000" doc:name="FileIn"/>
<mulexml:jaxb-xml-to-object-transformer jaxbContext-ref="JAXB_Context" doc:name="XML to JAXB Object" returnClass="se.razorlib.SystemAOrder.Header"/>
<custom-transformer returnClass="se.razorlib.SystemBOrder.SalesOrder" encoding="UTF-8" class="se.didriksson.Transformer.Map2SystemBOrder" doc:name="Map2B"/>
To pick the correct bean class you have to place the
#XmlRootElement(name = "Order")
Instead of order you may have to put the root element of your xml.
Another point
I also face an issue with mule 3.7 which is it doesn't read package.info file in the package

Resources