I am trying to create an app that will listen to JMS queue, process message and sends response to another JMS queue. As I understood the docs I can use JMS inbound gateway and some handler to process the request, something like this:
IntegrationFlows.from(Jms.inboundGateway(connectionFactory).defaultReplyQueueName(responseQueue)).handle(handler).get();
However I don't know how to set the input JMS queue via DSL. I found that via XML it can be done as following:
<int-jms:inbound-gateway id="jmsInGateway"
request-destination="inQueue"
request-channel="exampleChannel"/>
Sadly Jms.inboundGateway() does not allow to set request destination. How can I set it?
There are these two options for destination on that Spec:
/**
* #param destination the destination
* #return the spec.
* #see JmsListenerContainerSpec#destination(Destination)
*/
public JmsInboundGatewayListenerContainerSpec<S, C> destination(Destination destination) {
this.spec.destination(destination);
return _this();
}
/**
* #param destinationName the destinationName
* #return the spec.
* #see JmsListenerContainerSpec#destination(String)
*/
public JmsInboundGatewayListenerContainerSpec<S, C> destination(String destinationName) {
this.spec.destination(destinationName);
return _this();
}
So, your code snippet works for me like this:
return IntegrationFlows.from(
Jms.inboundGateway(connectionFactory)
.destination("inQueue")
.defaultReplyQueueName(responseQueue))
.handle(handler)
.get();
I'm not sure why is that not visible for you...
On the other hand I see your point. It is probably better to name that option as a requestDestination for consistency with the replyQueueName and the same option in the XML DSL. Feel free to raise a GH issue or even provide a contribution on the matter deprecating an existing destination option!
Related
I have a Tcp FailOverConnectionFactory supplied with two AbstarctClientConnectionFactory. Each AbstarctClientConnectionFactory will connect to different servers.
And Using TcpOutboundGateway for message exchange. Now i want to switch between the AbstarctClientConnectionFactory based on a Custom Health Check supported by the server.
For Example: If the Client sends message 'TEST HEALTH ', then server replies back as 'GOOD' or 'FAIL'. If the reply received is FAIL, then other AbstarctClientConnectionFactory has to be used for upcoming connections.
Please suggest if it is possible through Spring Integration Ip framework.
The logic is like this essentially:
/**
* Finds a connection from the underlying list of factories. If necessary,
* each factory is tried; including the current one if we wrap around.
* This allows for the condition where the current connection is closed,
* the current factory can serve up a new connection, but all other
* factories are down.
* #throws InterruptedException if interrupted.
*/
private synchronized void findAConnection() throws InterruptedException {
...
while (!success) {
try {
this.delegate = nextFactory.getConnection();
...
}
catch (RuntimeException e) {
if (logger.isDebugEnabled()) {
logger.debug(nextFactory + " failed with "
+ e.toString()
+ ", trying another");
}
...
}
}
}
So, you probably can override an AbstractClientConnectionFactory.getConnection() for your custom check and throw an exception if server returns FAIL.
There is nothing like that in the framework; the FailoverClientConnectionFactory simply fails over when the connection can't be established.
We would have to add some mechanism to the factory to "test" the connection after opening it.
I don't think it would be too difficult to do that; feel free to open a new feature issue on GitHub.
In the case of consumer failure after retries, I see the whole payload gets logged.
failedMessage=GenericMessage [payload=
Is there an easy way to mask it or hide it?
You need to declare your own errorChannel bean. It indeed could be the same PublishSubscribeChannel and declare your own LoggingHandler as a subscriber to that channel. Its:
/**
* Set a SpEL expression string to use.
* #param expressionString the SpEL expression string to use.
* #since 4.3
* #see #setLogExpression(Expression)
*/
public void setLogExpressionString(String expressionString) {
can be used to declare whatever you could log or want within an incoming Message context.
I'm trying to setup a Spring Integration flow using the DSL style flows mixed with #Bean definitions. In this example, I'm attempting to mediate an incoming REST request (restCustomerGateway) as an inbound webflux gateway. I saw that you can use .payloadExpression to pull things out of the request (in this case the id path parameter...would be intersted if there are better or more typesafe ways).
I then flow it into a webflex outbound gateway (restCustomerSource) to make a downstream call, which should then be funneled back to the inbound gateway as a response. Note, there will eventually be transformers in between to do payload transformation/etc.
Simple question is, how do I structure this so that I have access to the 'id' (the path parameter, currently hardcoded to '1' in the outbound gateway invocation)? I'm assuming this is part of the message payload that flows between the two, but how do I get a handle to it?
#Bean
public WebFluxInboundEndpoint restCustomerGateway() {
return WebFlux.inboundGateway("/rest/customers/{id}")
.requestMapping(m -> m.produces(MediaType.APPLICATION_JSON_VALUE)).payloadExpression("#pathVariables.id")
.get();
}
#Bean
public WebFluxRequestExecutingMessageHandler restCustomerSource() {
return WebFlux.outboundGateway("http://localhost:8080/customers/1").httpMethod(HttpMethod.GET)
.expectedResponseType(Customer.class)
.get();
}
#Bean
public IntegrationFlow restCustomerFlow(CustomerProcessor customerProcessor) {
return IntegrationFlows
.from(restCustomerGateway())
.handle(restCustomerSource())
.handle(customerProcessor)
.get();
}
There is a
/**
* Specify a {#link Function} to evaluate in order to generate the Message payload.
* #param payloadFunction The payload {#link Function}.
* #param <P> the expected HTTP request body type.
* #return the spec
* #see HttpRequestHandlingEndpointSupport#setPayloadExpression(Expression)
*/
public <P> S payloadFunction(Function<HttpEntity<P>, ?> payloadFunction) {
on the WebFluxInboundEndpointSpec, but you don't have there an access to the evaluation context variables or even to the original ServerWebExchange, only the RequestEntity is available in the function.
Since you stored that id path variable into the payload of the message to push downstream via payloadExpression("#pathVariables.id"), it is indeed available in the WebFlux.outboundGateway() for access.
You have there right now hard-coded uri, but you can use this variant instead:
/**
* Create an {#link WebFluxMessageHandlerSpec} builder for request-reply gateway
* based on provided {#code Function} to evaluate target {#code uri} against request message.
* #param uriFunction the {#code Function} to evaluate {#code uri} at runtime.
* #param <P> the expected payload type.
* #return the WebFluxMessageHandlerSpec instance
*/
public static <P> WebFluxMessageHandlerSpec outboundGateway(Function<Message<P>, ?> uriFunction) {
So, therefore your config becomes like this:
WebFlux.outboundGateway(m -> "http://localhost:8080/customers/" + m.getPayload())
<int-sftp:outbound-gateway id="sftpOutBound"
session-factory="sftpSessionFactory" expression="payload" command="put" request-channel="outboundFtpChannel"
remote-directory="/tmp/tsiftp" reply-channel="sftpReplyChannel"/>
with the above xml, i can send files and get reply . In java, how to set the remote directory in SftpOutboundGateway .If I use SftpMessageHandler,is there any possibility to get reply.Commented code is transferring files but no reply.
#Bean
#ServiceActivator(inputChannel = "outboundFtpChannel")
public MessageHandler transfertoPeopleSoft(){
/* SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
handler.setRemoteDirectoryExpression(new LiteralExpression("/tmp/tsiftp"));
return handler;*/
SftpOutboundGateway sftpOutboundGateway = new SftpOutboundGateway( sftpSessionFactory(), "put", "/tmp/tsiftp");
sftpOutboundGateway.setOutputChannelName("sftpReplyChannel");
return sftpOutboundGateway;
}
Exception I am getting is
exception is org.springframework.expression.spel.SpelParseException: Expression [/tmp/tsiftp] #0: EL1070E: Problem parsing left operand
Thanks for your help.
The remote directory for the SftpOutboundGateway can be configured by the SftpRemoteFileTemplate and its:
/**
* Set the remote directory expression used to determine the remote directory to which
* files will be sent.
* #param remoteDirectoryExpression the remote directory expression.
*/
public void setRemoteDirectoryExpression(Expression remoteDirectoryExpression) {
https://docs.spring.io/spring-integration/docs/5.0.0.RELEASE/reference/html/sftp.html#sftp-rft
Feel free to raise a JIRA for improvements on the matter.
I know that Expression variant isn't so useful because you need to use SpelExpressionParser or just LiteralExpression just for simple dir variant.
I am using Kue, a priority job queue backed by redis in node.js app.
I want to push a method of an instance to the queue so that it can be directly called when the queue is processed, something similar to as shown below.
This is an example from Larevel
class UserController extends Controller
{
/**
* Send a reminder e-mail to a given user.
*
* #param Request $request
* #param int $id
* #return Response
*/
public function sendReminderEmail(Request $request, $id)
{
$user = User::findOrFail($id);
$this->dispatch(new SendReminderEmail($user));
}
}
I'm a little confused as to how this can be achieved in my node app with Kue.