How to customize spring integration flow - java-8

I have a requirement like
File comes from FTP
File is copied to local directory
File is picked up
server 1 to parse and read
service 2 to enrich XYZ
service 3 to enrich CDY
service 4 to persist the data in the database and get the set the ids generated (as required later)
service 5 to enrich another piece of information based on service 4
service 6 will send a message to another system
service 7 will update the data again
service 8 will then do something etc
move file back to done directory
At thie point I am thinking about have one flow that will deal with FTP side and get the file and download it.
flow # 02
will pick the file and do the processing as explained above
My question is should I be using the transformers for all these steps above. Also is it ok if I have one flow with all the transformers or should I break it down in sub-flows?.
If any transformer throws an exception will it just ignore the rest of transformers and go to error channel?
Also if I put an exception handling channel will I actually know at which step the exception was thrown?

You really can do everything with transformers if you are not familiar with many other Spring Integration components, like Enricher: https://docs.spring.io/spring-integration/reference/html/message-transformation.html#content-enricher and JPA channel adapters: https://docs.spring.io/spring-integration/reference/html/jpa.html#jpa
You really can do everything in a single flow even if you are going to have several instances of your application. It is possible to configure a flow the way that every step can be distributed to the whole cluster for even computation. On the other hand I really split my flow to several of them for some logical units.
If one step throws exception, you indeed don't go downstream with that message any more. This works exactly the same way as regular Java program.
Yes, starting with some version we add a whole component into an exception message:
throw IntegrationUtils.wrapInHandlingExceptionIfNecessary(messageToUse,
() -> "error occurred in message handler [" + this + "]", e);
Pay attention to this. It will call toString() with a bean name and a configuration source to determine the place from the exception where in the flow an error happened.

Related

Atomically update database and send message. Outbox pattern or not?

You have a command/operation which means you both need to save something in database end send an event/message to another system. For example you have an OrderService and when a new order is created you want to publish an "OrderCreated"-event for another system/systems to react on (either direct message or using a message broker) and do something.
The easiest (and naive) implementation is to save in db and if successful then send message. But of course this is not bullet proof because the other service/message broker is down or your service crash before sending message.
One (and common?) solution is to implement "outbox pattern", i.e. instead of publish messages directly you save the message to an outbox table in your local database as part of your database transaction (in this example save to outbox table as well as order table) and have a different process (polling db or using change data capture) reading the outbox table and publish messages.
What is your solution to this dilemma, i.e. "update database and send message or do neither"? Note: I am not talking about using SAGAs (could be part of a SAGA though but this is next level).
I have in the past used different approaches:
"Do nothing", i.e just try to send the message and hope it will be sent. Which might be fine in some cases especially with a stable message broker running on same machine.
Using DTC (in my case MSDTC). Beside all the problem with DTC it might not work with your current solution.
Outbox pattern
Using an orchestrator which will retry process if you have not got a "completed" event.
In my current project it is not handled well IMO and I want to change it to be more resilient and self correcting. Sometimes when a service is calling another service and it fails the user might retry and it might work ok. But some operations might require out support to fix it (if it is even discovered).
ATM it is not a Microservice solution but rather two large (legacy) monoliths communicating and is running on same server but moving to a Microservice architecture in the near future and might run on multiple machines.

How to log all microservices logs in a single Log-file using springboot

I have 5 web applications which I developed using Springboot(A,B,C,D and E).
Below are the flow of 2 calls
First Flow:
A's Controllers --> A's Service --> B's Controller --> B'Service --> C's Controller --> C's Service --> C's Dao --> DB
SecondFlow:
A's Controllers --> A's Service --> D's Controller --> D'Service --> B's Controller --> B'Service --> C's Controller --> C's Service --> C's Dao --> DB
Once fetch/push data from/into the DB then the corresponding methods are returning some value. For each and every method logging the status (input details and returning status). I am able to see logs in each service separately. But I want to see complete one request-response(A's controller request to A's controller response) cycle logs in one file.
How Can I achieve it?
This is a ver bad idea, but let's take a step back and look at the problem instead of guessing a solution.
You have multiple applications that collaborate together to execute (distributed) transactions. You need to trace those interactions to see your dataflow. This is very useful for many reasons so it's correct that you care about it. It is also correct to collect all you log entries in a single sink, even if it won't be a file because it is not well suited to manage prodcution workloads. A typical scenario that many organization implements is the following
Each application send logs to files or standard output
For each node of you infrastructure there is an agent that reads that streams, does some basic conversion (eg. translates log entries in a common format) and send data to a certain sink
The sink is a database, the best technology option is a DBMS without strict requirements about data schema (you are storing everything in a single huge table after all) and transactional properites (if the data are logs, you are fine with an optimistic concurrency control). You also want some tool that is more good at reads than writes and have good performance in complex searches to drill down a large amount of structured data
a Dashboard to read logs, make searches and even create dashboard with synthetic stats about events
BONUS: use a buffer to manage load spikes
There are precise tools to do the job and they are
logstash/beats/fluentd
Elasticsearch....what else? ;)
Kibana, the favourite Elasticsearch client
BONUS: rabbimq/kafka/otherMessageBroker or Redis
but you still miss a step
Suppose you call a REST API, something simple like a POST /users/:userId/cart
API Gateway receives your request with a JWT
API Gateway calls Authentication-service to validate and decode the JWT
API Gateway calls Authorization-service to check if the client as right to perform the request
API Gateway calls User-service to find :userId
User-Service calls Cart-service to add the product on :userId cart
Cart-Service calls Notification-Service to decide whether is needed to send a notification for the completed task
Notification-Service calls Push-Gateway to invoke an external push notification service
....and back
to not get lost in this labyrinth you NEED just one thing: the correlation ID
Correlation IDs attach a unique ID to all interaction beetween these microservices (headers in HTTP calls or AMQP messages, for instance) and your custom log library (because you've already built a custom logging library and shared it among all the teams) capture this ID to include it in every log entry wrote in the context of the single request processed from each of those microservices. You can even add that correlation ID in the client response, catch it if the respone carry out an error code and perform a query on your logs DB to find all the entries with the given correlation ID. If the system clock works, they will be retrieved in the correct time order and you will be able to reconstruct the dataflow
Distributed Systems make everything more complicate and add a lot of overhead on things that we ever done before, but if you put in your pocket the right tools to manage the complexity, you can see the benefits
you can implement central logging system like:
The ELK stack (Elastic Search, Logstash and Kibana) for Centralized Logging.

How to maintain order of messages being processed in a mule flow from VM to JMS using one-way message exchange pattern?

I am using mulesoft ESB with Anypoint studio for a project. In one of my flows I am using one-way message exchange pattern to dispatch from VM (persistence file store VM connector) to JMS, both xa transaction enabled to avoid losing messages.
Consider a scenario where we send a message every time user updates his/her last name to ESB. For example, let's say user changes last name to 'A', but quickly changes to 'B', so final result is expected to be 'B'.
1) Is it likely that message 'B' gets processed before message 'A' in my case? and thus last name being set to 'A' instead of 'B'?
2) How do I avoid that apart from using 'request-response' MEP?
3) Is there a way to write unit tests for making sure order of messages being processed is maintained from VM (one-way, xa enabled) to JMS (one-way, xa enabled)?
4) How do I go about testing that manually?
Thank you in advance. Any pointers/help will be appreciated.
It's not likely, since your system would normally react way quicker than a user can submit requests. However, that may be the case during a load peak.
To really ensure message order, you really need a single bottleneck (a single instance/thread) in your solution to handle all requests. That is, you need to make sure your processing strategy in Mule is synchronous and that you only have a single consumer on the VM queue. If you have a HA setup with multiple Mule servers, you may have potential to get messages out of order. In that case, and if the user initially is connected using HTTP, you can get around most of the problem using a load balancer with a sticky session strategy.
A perhaps more robust and scalable solution is to make sure the user submits it's local timestamp on each request with high resolution. Then you can make sure to discard any "obsolete" updates when storing the information into a database. However, that is not in the mule VM/JMS layer, but rather in the database.
For testability - no, I don't think there is a truly satisfying way to be 100% sure messages won't come out of order during any condition by just writing integration tests or performing manual tests. You need to verify the message path theoretically to make sure there is no part where one message can bypass another.

Add Batch capabilities to Integration flow

I currently have a Spring Integration flow that works fine (see link for diagram). I would like to add Batch on top of my current configuration to allow for retry with exponential back-off, circuit breaker pattern, and persisting jobs to the database for restart.
The Integration flow consists of a Gateway that takes a Message<MyObj>, which is eventually routed to a Transformer that converts Message<MyObj> to a Message<String>. The Aggregator then takes Message<String> and eventually releases a concatenated Message<String> (using both a size release-strategy and a MessageGroupStoreReaper with a timeout). The concatenated String is then the payload of the File uploaded using SFTP outbound-channel-adapter.
I have searched, read through docs, looked at tons of examples, and I can't figure out how to encapsulate the last step of the process into a Batch Job. I need the ability to retry uploading the String (as payload of File) if there is an SFTP connection issue or other Exception thrown during the upload. I also want to be able to restart (using database backed JobRepository) in case of some failure, so I don't think using Retry Advice is sufficient.
Please explain and help me understand how to wire together the pieces and which to use (job-launching-gateway, MessageToJobRequest Transformer, ItemReader, ItemWriter??). I'm also unsure how to access each Message<String> and send to the SFTP channel-adaptor inside of a Job, Step, or Tasklet.
Current flow:
First of all let's take a look how we can overcome your requirements without Batch.
<int-sftp:outbound-channel-adapter> has <request-handler-advice-chain>, where you can configure RequestHandlerRetryAdvice and RequestHandlerCircuitBreakerAdvice.
To achieve the restartable option you can make the input channel of that adapter as a persistent queue with message-store.
Now about Batch.
To start a Job from the Integration flow you should write some MessageToJobRequest and use <batch-int:job-launching-gateway> after that. Here, of course, you can place your payload to the jobParameters.
To send a message from Job to some channel (e.g. to sftp adapter) you can use org.springframework.batch.integration.chunk.ChunkMessageChannelItemWriter.
Read more here: http://docs.spring.io/spring-batch/reference/html/springBatchIntegration.html

Expose process definition as a web service in tibco designer

I'm trying to expose a process definition in TIBCO BW Designer 5.7 as a web service, but I've run into some snags. For some reason, I cannot start the Generate Web Service Wizard, because my process does not appear in the "Add More Processes to interface" list.
I've been searching online but to not much avail. What I've gathered is that I need to reference external schemas (using XML Element Reference) in my input (Start) and output (End), which I have done so. So what could be possibly wrong?
Do I need to include any Process Variables or Partners under the Process Definition?
I'm very new to Designer so would appreciate some help here!
To expose a BusinessWorks process as a web service you need to use a WSDL message as input and output (and optionally error output). If you already have a process that is used by other processes and do not want to change input/output schema you could create another process that essentially wraps your initial process but expose input/output as WSDL messages. My suggestion would be to follow these approximate steps
Create a XML schema containing the input and output formats
Create a WSDL resource
Add two Message resources (input/output), reference the above XML schema
Add a PortType resource
Add an Operation resource referencing the two Message resources as input and output
Set input/output of the process to expose to the WSDL messages defined above
Create a Service resource
Add the WSDL operation to the Service interface
Set the implementation of the operation to your process definition
Add a SOAP endpoint with a HTTP transport
Add the Service resource to your Process Archive
For more details on the parameters that can be used, see the BusinessWorks Palette Reference documentation.
the most common mistake in this case is that you don't use a XML schema for the input and output, make sure that you have one for every process you have in your project and then you can continue with your web service generation.
Kind Regards

Resources