closed as unclear what you're asking by Wooble, Reeno, gnat, Oldskool, Hanlet EscañoNov 17 '15 at 19:35
1 Answer
Spring-WS
) is a product of the Spring community focused on creating document-driven
Web services. It aims to facilitate contract-first SOAP service development. Some of its key features are:
- Powerful mappings The incoming XML requests can be distributed to any
object
, depending onmessage payload
, SOAP Action header, or an XPath expression. - XML API support Incoming XML messages can be handled not only with standard
JAXP
APIs such asDOM
,SAX
, and StAX, but also JDOM, dom4j, XOM, or evenmarshalling
technologies. - Flexible XML Marshalling Spring Web Services builds on theObject/XML Mapping module in the Spring Framework, which supports
JAXB 1
,JAXB 2
,Castor
,XMLBeans
,JiBX
, andXStream
. - Reuses your Spring expertise Spring-WS uses
Spring application contexts
for all configuration, which should help Spring developers get up-to-speed nice and quickly. Also, the architecture ofSpring-WS
resembles that ofSpring-MVC
. - Supports WS-Security WS-Security allows you to
sign
SOAP messages,encrypt and decrypt them, orauthenticate
against them. - Integrates with Spring Security The WS-Security implementation of Spring Web Services provides integration with
Spring Security
.
Spring-ws
:
Not the answer you're looking for? Browse other questions tagged javaspringspring-mvcsoap or ask your own question.
This article demonstrates how to develop non-blocking, end-to-end integration with external systems in Spring-based applications using a loan broker example from the Enterprise Integration Patterns book.
Request per thread is an old beast and should be avoided as much as possible. It not only affects an application's scalability but can also lead to cascading failures. Event driven architecture is an excellent software architecture pattern for effective utilization of resources. In the context of non-blocking services, it helps in allocating threads only when the response is ready for processing.
This article demonstrates how to develop non-blocking, end-to-end integration with external systems in Spring-based applications. To illustrate a moderately complex integration problem, I have chosen a well-known loan broker system example from the enterprise integration patterns book. For those who are not aware of this example, it is a system that gathers quotations from different banks for a loan request. This helps applicants in selecting the best available quotation.
To keep the illustration short and to the point, I have intentionally avoided a few integration points/constructs from the original example. Also, the loan broker system below only returns the best quote in terms of interest the applicant has to pay by the end of the year, along with the principal amount. The example mainly relies on Spring MVC, Spring integration, and Spring Boot projects from the Spring stack. Integration with bank stubs is done via JMS queues and for that I have used ActiveMQ. The diagram below depicts the internals of loan broker system.
As shown in above diagram, the loan request arrives at LoanBrokerController then it is dispatched to multiple banks, and after that an aggregated response is sent back to the user. Each timeline in the diagram is labeled with its respective thread name. In this whole process of request/response the container keeps accepting the requests and does not block for any external interaction. The dotted lines shows JMS asynchronous communication with banks. This way we parallelize the requests to banks for quotation and aggregate the response before sending it back to the controller. The captions below different swimlanes highlight integration flows that are employed for orchestrating the whole system.
Below is the basic gateway interface along with controller from which it is invoked:
As you can see in the above code snippet LoanBrokerGateway returns ListenableFuture, which tells the caller that the response will be available at some point in time in future. Hence, we can use DeferredResult to release the requesting thread and send the response from a different thread. The connection will remain open by the Servlet >= 3.0 container, till the response arrives or times out. Timeout value is provided in DeferredResult object during initialization. The validation check at line 29 is added just to ensure the response should match the best available quotation, otherwise, send a conflict error. I hope it is quite simple to follow so far, now let's dive into spring integration flows one by one in the same order shown in the above diagram from left to right, beginning with 'loan-broker-scatter ' integration flow.
Spring Mvc 40 Restful Web Services Simple Example Resume
In reference to the line numbers, below is the description of activities performed in loan-broker-scatter integration flow:
-
At line (2), while configuring the gateway, I have kept async-executor empty to disable gateway's default async handling. The reason I did that was I want to explicitly handle the async behavior of gateway instead of letting gateway create another thread pool and return listenable future.
-
At line (11), I am explicitly creating an instance of SettableListenableFuture. Later, I will return it to gateway so that it can safely release the calling thread.
-
At line (13), I am creating a custom message header with the name 'loan_broker_slector' using SPEL. It internally calls a static 'nodeIdentifier' function of NodeIdentificationUtil class. This class generates a unique identifier for a node. This message header will then be used as selector later while collecting messages from banks output queues. This will ensure messages generated from a node should return to itself.
-
At line (19), I am storing the ListenableFuture in the message store, so that later we can send the response back to the controller.
-
In header enricher at line (21), I am saving the claim-check identifier into header after converting to string. After that, I am creating two custom headers 'correlation_id' and 'sequenceSize'. These headers are required to aggregate the result in loan-broker-gather integration flow. I have kept 'sequenceSize' to '2', because I already know that number of banks to whom I have to send the request are also two.
-
As I want to send the same copy of the loan request to multiple banks, I have used a pub-sub channel at line (31). I would have used apply-sequence option in pub-sub to implicitly set sequenceSize, correlationId, and sequenceNumber headers, but correlationId was getting screwed up by JMS outbound adapters. I have not set 'sequenceNumber' header, because the order of responses from different banks does not matter.
-
At line (55), I am scheduling a MessageGroupStoreReaper for erasing timed out messages from the message store. This helps in avoiding out of memory errors.
I am skipping both banks flow, as those are only stubs, but are part of an example available on GitHub. Let's now move to loan-broker-gather integration flow.
Loan broker gather flow is the inverse of a scatter flow. In reference to the line numbers, below is the description of activities performed in this integration flow:
-
At line (2) and (11) it is picking the response from output queues of banks. To make sure the response should come to the same node, I have mentioned same message selector used at the time of scattering the message.
-
At line (24), it aggregates the response of both banks into a list. As a release strategy, we have mentioned that the size of the response list should be equal to '2'. Also, I have specified custom correlation identified at line (25) to correlate the responses with each other.
-
At line (31), it transforms the list outcome of the aggregate by selecting minimum interest rate from the list.
-
At line (47), I am saving the best quotation into the header, because I have to check out the listenable future from the message store in downstream to set the result.
-
At line (60), I am explicitly setting the result on listenable future we checked out from the message store. This will then invoke the listenable future callback functions in the controller, wherein which we hand over the result to container by setting result on DeferredResult.
-
At line (68), I am scheduling a MessageGroupStoreReaper for erasing timed out messages from the message store.
Outcome:
Below is the log captured from one of the executions of a loan request. I have selectively picked only interesting events from the logs. Just observe how each step to process request transitions from one thread to another. Each log event captured below can be represented using the below format:
'[thread] SimpleClassName - logMessage'
-
Line (1) shows the event at which the request arrives at spring MVC dispatcher servlet.
-
Line (3) & (5) shows JMS messages being sent to both banks' inbound queues on same HTTP request processing thread.
Yeshu Ke Naam Ki Jai Jai Ho Hindi Christian Song Hindi Gospel Song With Lyrics Video Hindi Jesus New is popular Free Mp3. Yeshu Ke Naam Ki Jai Jai Ho Hindi Christian Song Hindi Gospel Song With Lyrics Video Hindi Jesus New. Play and Listen yeshu masih ki jai lyrical video this song speaks about miracles and wonders done by jesus lets. Jaane Ye Kya Ho gaya Hai Mujhey G C Tu Jabse Aaya, Iss Dil ME Mere F Chahe Ye Duniya Hum Pe Haase. (Lyrics + Chords) Ankur Masih. Song-Tera Lahoo Bada Kimti Hai Prabhu. Le Chal Mujhe(ले चल मुझे)[Lyrics + Chrods] Rock N Roll Yeshua Band. Jai Jai Prabhu Yeshu Ki(जय-जय प्रभु यीशु की). Rab kary tum ko b piyar ho jai. -
Line (7) shows spring MVC registering AsyncContext with the container and keeping the connection open for response at line (8). This happened because we are returning DeferredResult from LoanBrokerController.
-
Line (10) & (14) shows loan requests processing by different bank stubs at different points in time. I have put a random delay in each stub between 1000 to 1500 ms. Hence, the order of processing will vary on each execution.
-
Line (12) & (16) shows the request reaching to an aggregate component of spring integration via message-driven-channel-adapter, which internally use DefaultMessageListenerContainer.
-
Line (18) shows aggregate group completion when quotation response from banks reaches to aggregate. Here onward it uses the same thread on which aggregation completes. So whichever response completes the aggregation, that response thread will be used to set the result on ListenableFuture, which eventually sets result on DeferredResult. That is why until line (22) each activity occurred on the same thread.
-
Lines (24) and (26) show spring MVC sending the response back to the client on a different thread compared to the request.
Restful Web Services Example In Java
Final Thoughts:
Theway I have developed the non-blocking loan broker system may not be the only way, but it is very close to event driven architecture. As shown in the outcome section, each thread kicks in whenever there is an event to process. I have not used any of the blocking constructs like JMS gateway from spring integration. JMS response messages are only processed when they are ready. Until then there is no overhead of threads on the server. Also, I did not utilized proxy gateway default async behavior to avoid blocking the calling threads from controller, in case someone wants to use JMS gateway to keep integration flows simple. That way we would still be prone to request per thread issues. I understand it is bit complex, but it pays off at the end, when scalability is more demanding. Moreover, you can even avoid circuit breaker pattern, because with this way of integration there is no thread waiting for response.
I hope you enjoyed the article. The complete source code is available on GitHub. I have also kept the JMeter test along with source code, just in case you want to load test loan broker system by yourself. Your comments are more than welcome.