I need to dynamically assign messages to MessageChannels in my Spring Integration Context.
I can do this by getting the MessageChannel bean from the context when I know the names of the MessageChannel I want.
What I need to do is programatically find the name/id of the message channel(s) that are set in my ChannelAdapter/Service.
However, the MessageChannel API does not have a getName() or getId() method associated with it.
Is there a way to find this piece of information?
Thanks in advance.
Let's take look at this task from other side!
What is the reason to get deal with such low API like channels?
Why just don't use the Router pattern on the matter?
If I understand correctly, you want to have some dinamic routing, where you determine a destination channel by some Message property.
So it might be enough just use an expression router:
<int:router input-channel="input" expression="payload.theChannel"/>
Related
I am trying to build an integration solution where
IntegrationFlows
.from(inBoundGateway)
.enrichHeaders(enrichHeaders())
.transform(dto to externaldto)
.handle(outBoundGateway, advice -> advice.advice(retryAdvice()))
.transform(exetrnaldto to dto)
.get()
#Bean
RequestHandlerRetryAdvice rhra
rhra.setRecoveryCalBack(errorMessgaeRecoverer());
#Bean
ErrorMessageSendingRecoverer errorMessgaeRecoverer
and my outboundgateway is defined as
Http.outboundGateway(uri, resttemplate)
...
.get()
new RestTemplate(requestFactory)
where requestFactory is
TrustStratgey ts = new TrustStratgey(){
public boolean isTrusted(...){
return true;
}
}
SSLContext context = SSLContexts,custom().loaddTrustMaterials(null, ts);
SSLContextFactory cf = new SSLContextFactory(context, new NoopHostnameVerifier());
HttpClientBuilder clientBuilder ..
clientBuilder.setSSLSocketFactory()
Happy path works fine, the problem i am facing is with not so happy path.
When Api call returns Error response .transform(exetrnaldto to dto) fails and client get 500
I want to translate error resposne json as well to my json
How do i handle error situations.
My questions are;
How to handle errors.
In error conditions how to stop flow not to transform
How to send status code in response from outbound to client (this is important)
How to handle error like typical #Controller Advice #ErrorHandler mechanism or similar.
Hope Garry get to see this post, couldnt find any answers, i looked through many books and forums, feels like Java DSL is not widely used or commented yet.
There is nothing Spring Integration Java DSL specific in your question.
It is really more about how to handle HTTP error on the server side (MVC - HttpInboundGateway) and on the client side - RestTemplate and HttpOutboundGateway.
The Java DSL is just a syntax sugar over existing technologies and solutions.
So, the #Controller Advice #ErrorHandler is an MVC, server side. You definitely can make it working with the HttpInboundGateway, but it is indeed wrong direction for the client side REST calls.
It looks like you would like to catch a REST error call for that your .handle(outBoundGateway). Consider to use an ExpressionEvaluatingRequestHandlerAdvice along side with that retryAdvice. So, you will be able with its failureChannel to handle an exception and transform it into a desired JSON respectively.
See more in docs: https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints.html#expression-advice
I am using SpringBoot 2.0 with Spring Integration 5.0.3 and have an issue with my HTTP.inboundGateway. My goal is to validate the JSON posted to the gateway, because the request pojo consists of mandatory fields.
#Bean
public IntegrationFlow notifyUpdateVehicleFlow() {
return IntegrationFlows.from(Http.inboundGateway("/update")
.requestMapping(r -> r.methods(HttpMethod.POST))
.requestPayloadType(RequestPojo.class)
.requestChannel(updateChannel())
.replyChannel(updateReplyChannel()))
.get();
}
Is there an easy way to validate fields in the pojo have been set? What I have already tested is using #NotNull SpringValidation but it seems not to be supported with Spring Integration.
Greetings,
smoothny
There is no such a functionality in the Spring Integration. You can use .filter() downstream that Http.inboundGateway() and really perform Validator.validate() from there on the payload.
If you think it must be done somehow on the Http.inboundGateway() and you have strong requirements and clean description, feel free to raise a JIRA on the matter and we will discuss what can be done from the Framework perspective.
Currently, code similar to the following exists in one of our applications:
#Component
public class ProcessRequestImpl {
private ExecutorService executorService;
public processRequest(...) {
// code to pre-process request
executorService.execute(new Runnable() {
public void run() {
ProcessRequestImpl.this.doWork(...);
}
}
}
private void doWork(...) {
// register in external file that request is being processed
// call external service to handle request
}
}
The intent of this is to create a queue of requests to the external service. The external service may take some time to process each incoming request. After it handles each one, it will update the external file to register that the specific request has been processed.
ProcessRequestImpl itself is stateless, in that all state is set in the constructor and there is no external access to that state. The process() method is called by another component in the application.
If this were to be implemented in a Spring Integration application, which of the following two approaches would be best recommended:
Keep the above code as is.
Extract doWork(), into a separate endpoint, configure that endpoint to receive messages on a channel, and to use configuration to achieve the multi threading in place of the executor service.
Some of the reasons we are looking at Spring Integration are as follows:
To remove the workflow logic from the code itself, so that the workflow and the chain of processing is evident on a higher level.
To simplify each class, enhancing readability and testability.
To avoid threading code if possible, and define that at a higher level of abstraction in configuration.
Given the sample code, could those goals be achieved using Spring Integration. Also, what would be an example of the DSL to achieve that.
Thanks
Something like
#Bean
public IntegrationFlow flow() {
return IntegrationFlows.from(SomeGatewayInterface.class)
.handle("someBean", "preProcess")
.channel(MessageChannels.executor(someTaskExecutorBean())
.handle("someBean", "doWork")
.get();
The argument passed to the gateway method become the payload of the preprocess method, which would return some object that becomes the message payload, which becomes the parameter passed to doWork.
I have a general question. We are upgrading some old code to v4.1.3 of spring-integration. Let's say we have a service activator that receives a domain object of type Foo, and returns the same object on the output channel (after changing some properties of that object).
Our existing code has signatures like below. Is it the right convention? If I don't need the headers, can I return my payload directly and will the framework wrap it into a Message?:
public Message<Foo> computeValue(Foo payload, #Headers Map<String, Object> headerMap) {
//...
return MessageBuilder.withPayload(payload).copyHeaders(headerMap).build();
}
Yes, you don't need do that. More over that is pointless because in case of Service Activator the Framework populates request headers to the reply message independently of your effort.
So, consider do not care about headers at all if you don't need to do some specific logic on the matter.
Can we use somehow "subflows" in Spring Integration?
I have many different processes which would use the same "subflow". These processes have always the same part which would be good to be put into a separate file.
What would be the corrent way to implement these flows?
I tried to find a solution to use subflows in Spring Integration but I could not find anything.
One simple technique is to put the subflow in a separate file with "well-known" input and output channels (the subflow starts with one channel and ends with another). Then, simply <import/> the subflow and send/consume to/from the input/output channel.
Or, instead of an import you can use the Java DSL to define the subflow and add it to your application contexts that need the subflow...
#Configuration
public class MySubflowDefinition {
#Bean
public IntegrationFlow subflow() {
return IntegrationFlows.from("someInChannel")
.transform(...)
...
.channel("someOutChannel")
.get();
}
}
For a more formal "subflow" definition, see the spring-integration-flow extension. This solution also allows the same subflow to be invoked from multiple places in the same application context.
spring-integration-java-dsl and spring-integration-flow are both available in the spring repo and maven central with (currently) versions 1.0.0.RELEASE.