Http Outbound Gateway Sending Json request from pojo payload - java

I'm trying to send a simple POST request to a REST endpoint. I have a simple pojo that I would like to send in the payload as JSON. Here is the pojo (note I'm using Spring Integration with grails so the pojo/service are in Groovy):
class Person implements Serializable {
String name
}
Here is my gateway:
public interface PersonGateway {
Person savePerson(Person person)
}
Here are the important parts of the wiring:
<int:channel id="requestChannel" />
<int:channel id="responseChannel" />
<int:header-enricher input-channel="requestChannel">
<int:header name="Content-Type" value="application/json" />
</int:header-enricher>
<int:gateway id="PersonGateway"
service-interface="com.example.PersonGateway"
default-request-channel="requestChannel"
default-reply-channel="responseChannel">
<int:method name="savePerson" />
</int:gateway>
<int-http:outbound-gateway url="http://127.0.0.1:8000/person"
http-method="POST"
message-converters="jsonConverter"
expected-response-type="com.example.Person"
request-channel="requestChannel"
extract-request-payload="false"/>
This POST request never reaches that service but doesn't throw any exceptions. When I log all levels the only thing I get that looks like a clue is:
2014-03-30 16:35:07,313 [main] DEBUG
outbound.HttpRequestExecutingMessageHandler - Unable to attempt
conversion of Message payload types. Component
'org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler#0'
has no explicit ConversionService reference, and there is no
'integrationConversionService' bean within the context.
Other than that it doesn't give me much. I've been trying little things all day and can't seem to get anywhere. Anyone see what I am missing? Thanks!

Unable to attempt conversion of Message payload types.
Don't worry: it doesn't have value for you. In most cases we can live in our application without that integrationConversionService. Here it is needed for expressions. Since you don't use any expression, that WARN doesn't hurt you.
You say that you are going to send POJO as JSON, then you shouldn't use extract-request-payload="false". With false the <int-http:outbound-gateway> places to the request body entire Message<?> and changes content-type to application/x-java-serialized-object
Hope your jsonConverterdoes the correct stuff around POJO <-> JSON

Related

having spring integration tcpserver to manage clients and send them messages

I have already created a simple tcp server with spring integration which keeps a connection alive and responses to each request during the connection.
In that requestMethod, I'm also able to read the MessageHeder to get the connectionId.
Now I want to send messages from the server to the client.
As far as i understood the documentation i need to put the connectionid in the MessageHeader and then send the message. But I can't figure out how to do the latter one. I have the Message ready but how do i send/push it out?
Here is my xml-configuration:
<bean id="lfSerializer" class="org.springframework.integration.ip.tcp.serializer.ByteArrayLfSerializer"/>
<int-ip:tcp-connection-factory
id="socketserver"
type="server"
port="30124"
using-nio="true"
deserializer="lfSerializer"
serializer="lfSerializer"
single-use="false"/>
<int-ip:tcp-inbound-channel-adapter id="inboundServer"
channel="inputChannel"
connection-factory="socketserver"/>
<int-ip:tcp-outbound-channel-adapter id="outboundServer"
channel="outputChannel"
connection-factory="socketserver"
/>
<int:channel id="inputChannel">
<int:interceptors>
<int:wire-tap channel="logger"/>
</int:interceptors>
</int:channel>
<int:channel id="outputChannel">
<int:interceptors>
<int:wire-tap channel="logger"/>
</int:interceptors>
</int:channel>
<int:logging-channel-adapter id="logger" level="DEBUG" log-full-message="true"/>
<int:service-activator input-channel="inputChannel"
output-channel="outputChannel"
ref="echoService"
method="test"/>
<bean id="echoService"
class="com.examples.EchoService" />
I also tried to create a bean and another serviceactivator for output, then autowired that bean and called it's "send" method, but I don't know what to implement in that send-method to send out a message.
If it's a simple request/response scenario use an inbound gateway instead of channel adapters and the framework will take care of the correlation for you. This is used in the sample app. Simply have your POJO method return the reply payload.
If you want to send arbitrary messages to the client (i.e. NOT request/reply but, say, in, out, out, in, out, out, out etc) then, yes, you need to build the messages yourself, inserting the ip_connectionId header.
To send them, there are several options:
Inject outputChannel into your code
#Autowired
private MessageChannel outputChannel;
Use a MessagingTemplate to send to the channel (or simply call its send(Message<?> message) method directly).
Or
Use a MessagingGateway with a void return method and inject the gateway into your code.
EDIT:
Note, that if you want to start sending messages before receiving anything, you can obtain the connection id via the connection opened event.

Spring Integration: SMTP server

I am using Spring Integration 4.1.2.
In the program flow, at the end of a process I need to send an email. I am using the following:
<int:payload-type-router input-channel="response.in">
<int:mapping type="java.lang.String" channel="response.out"/>
<int:mapping type="org.springframework.mail.SimpleMailMessage" channel="mail.out"/>
</int:payload-type-router>
<mail:outbound-channel-adapter channel="mail.out" mail-sender="mailSender"/>
This is working fine.
I want to also handle the situation when the mail server is down.
I've tried the following solution but it does not work.
<int:chain input-channel="errorChannel" output-channel="emailErrorChannel">
<int:transformer ref="errorUnwrapper" />
</int:chain>
And the unwrapper:
#MessageEndpoint
public class ErrorUnwrapper {
#Transformer
public Message<?> transform(final ErrorMessage errorMessage) {
Message<?> failedMessage = ((MessagingException) errorMessage.getPayload()).getFailedMessage();
return failedMessage;
}
}
But this is not working. I want to catch the exception and send a meaningful response back to the user instead of a stacktrace. And I want to do this within Spring Integration. Otherwise I'll have to write a Java mail service call with a service-activator instead of the SI mail extension.
Or is it a one-way component? I've just found this blog post doing the same. I've also read this but got nowhere.
You likely need to add the errorChannel to whatever starts you flow; you need to show us the rest of your configuration.
Alternatively, you can add an ExpressionEvaluatingAdvice to the mail adapter; see this sample for an example of using the advice.

Copy mule variable data or mule property like payload to spring bean property

I am having a mule flow in which I am having a variable to which payload is copied as follows:
<set-variable variableName="originalPayload" value="#[payload]" doc:name="Variable" doc:description="Variable having copy of original payload present in soap request."/>
After this there is an interceptor that validates header of soap message and if validation fails then I need the above variable's data in interceptor to prepare custom fault message. Below is my configuration for Soap Proxy doing above:
<cxf:proxy-service port="XXX" namespace="XXX" service="XXX" payload="body" wsdlLocation="XXXX" doc:name="SOAP" doc:description="Soap proxy intercept soap request and apply header validation. Authentication and custom header will be validated for presence, content, and structure.">
<cxf:inInterceptors>
<spring:bean id="XXXX" parent="XXXX">
<spring:property name="sourceApplication" value="${sourceApplication}"/>
<spring:property name="originalMessage" value="#[originalPayload]"/>
</spring:bean>
</cxf:inInterceptors>
</cxf:proxy-service>
In above I need the value of originalPayload variable in originalMessage property of spring bean. If I can copy #[payload] directly it will work too. Above expression in spring property is not valid so it is not working.
Please suggest how to go for this.
Implementing Callable can be one option but I do not want to change the code written already unless there is no solution for above.
I tried to search for solution on this but could not find anything.
Thanks
Harish Kumar
The problem with your solution is that spring properties are set at configuration time whereas the #[payload] expression could be only resolved at runtime.
However within your interceptor you could retrieve the original payload from the CXF message by doing something like this:
MuleEvent event = (MuleEvent) message.getExchange().get(CxfConstants.MULE_EVENT);
Collection<Attachment> a = event.getMessage().getInvocationProperty("originalPayload");
You can refer to this interceptor as an example

Spring WS 2.1.0: Endpoint interceptors order

I have a web service on Spring WS with two endpoint interceptors. XML configuration looks like this
<sws:interceptors>
<bean class="org.someorg.security.SignatureInterceptor"/>
<bean class="org.someorg.common.LoggingInterceptor">
<constructor-arg value="logger_1"/>
</bean>
</sws:interceptors>
SignatureInterceptor verifies signature of incomming SOAP Envelope and signs outgoing SOAP Envelope.
LoggingInterceptor stores raw SOAP data (byte array) in a database.
I need SignatureInterceptor to invoke before LoggingInterceptor and writing interceptor beans this way I expected it would solve my problem. But according to log messages LoggingInterceptor invokes first, so unsigned data stores in a database.
Then I changed configuration simply swaped bean declarations and they began to work as I expected
<sws:interceptors>
<bean class="org.someorg.common.LoggingInterceptor">
<constructor-arg value="logger_1"/>
</bean>
<bean class="org.someorg.security.SignatureInterceptor"/>
</sws:interceptors>
But this case is not clear to me. How can I explicitly set the invoke order of interceptors?
The order should be the way you have specified it (except if they are mapped to a specific endpoint url, in which case they are handled last) - do note that the order in which the order in which the handleResponse is handled is opposite of handlRequest -
Ideally in your case you should see:
SignatureInterceptor.handleRequest(..)
LoggingInterceptor.handleRequest(..)
Endpoint handles request
LoggingInterceptor.handleResponse()
SignatureInterceptor.handleResponse()
I tried a small test and it works the same way for me.

accessing initial exchange message in camel

Hi guys I have the following situation when I need to have "composite" process for the XML request. This is snippet from my spring route definition:
<route id="request1">
<from uri="activemq:request1" />
<unmarshal ref="integrationServerJaxb" />
<bean ref="createTINValidationMessage" />
<bean ref="switchComponent" />
<bean ref="createCreateTINMessage" />
<bean ref="switchComponent" />
<bean ref="createResponse1" />
<marshal ref="integrationServerJaxb" />
</route>
Basically what I want to achieve is:
grab a message from request1 message queue
create TIN VALIDATION message from it
send TIN VALIDATION message to the switch
wait for the switch response
with the switch response from step 4 AND initial request 1 XML message, create CREATE TIN message
send message (from step 5) to the switch
create response XML based on response from switch (from step 6)
So in other words, I need to get hold of initial message during processing. In the CreateCreateTINMessage bean I can change the method parameter to Message type, then it will be mapped to the actual Camel Message (from the previous step though), not the very first message in the exchange. Inspecting the message's exchange, I could trace the initial JMS message with request1 xml payload but getting that deep does not seem right. My question is, is it possible to somehow perform integration with intermediary result and initial message from the route? Thank you.
sure, just preserve it explicitly in an exchange property (or message header)...
from(...)
.setProperty("ORIG_EXCH",body())
...
.process(new Processor() {
public void process(Exchange exch) throws Exception {
Object orig = exch.getProperty("ORIG_EXCH");
...
}
})
...
or you can use this API to retrieve it from your route...
exchange.getUnitOfWork().getOriginalInMessage();

Categories