Spring Integration Async Gateway Response Handling - response

I need some hint how to solve a problem with Spring Integration.
I have a Gateway interface.
public interface OrderGateway {
Future<Response> process(Request value);
}
I send a request message via the gateway. The ValidationService should check if the data is correct. If yes it should forward the message to the OrderService. The OderService will generate a response.
But if the request data is not correct the ValidationService should generate a response object return it to the gateway. In that case the OrderService should no be invoked. What kind of message endpoint would be the ValidationService? Would it bit a Router? I would like to a avoid handling this by throwing an exception. How to solve such a situation with Spring Integration?
+--------------------------------+
v |
Async Gateway --> CH --> ValidationService --> CH --> OrderService +
^ |
|---------------------------------------------------------------|
Thanks in advance.

The normal way to handle this would be to throw an exception and add an error-channel on the gateway; handle the error there and return the validation response from there.
If that's not suitable then, yes, a payload type router would work, with the validation result being sent to a "bridge to nowhere" (a bridge with only an input channel) and the framework will route it back to the gateway.

Related

Are all elements in a POST requests body mandatory?

If a POST request requires that i send four data elements in the body, like:
{
"name":abc,
"surname":xyz,
"contact_no":1234,
"address":random_value
}
What will happen if I miss out some of the elements, for example if I call the web service with elements like,
{
"name":abc,
"surname":xyz,
}
What error is the server likely to throw ? I am having this issue because I am making a API call and it's giving me a HTTP error 500, so I guess it's not an error on my part, but this is one doubt i wanted to clear. Thanks in advance.
Its depends on the service structure (if all fields are mandatory or not),
and HTTP error (500) returns to server error or (server or link) not found .

Not getting SPRING.SESSION.ID from headers

I'm using spring session and AbstractSessionWebSocketMessageBrokerConfigurer and am trying to create a STOMP Websocket with support for Spring Security and Spring Session. I can't seem to get my session activated. I use webstomp-client to connect (https://github.com/JSteunou/webstomp-client)
AbstractSessionWebSocketMessageBrokerConfigurer creates
#Bean
#SuppressWarnings("unchecked")
public SessionRepositoryMessageInterceptor<S> sessionRepositoryInterceptor() {
return new SessionRepositoryMessageInterceptor<S>(this.sessionRepository);
}
I pass as header to both the connect event and every message
SPRING.SESSION.ID:<My session id>
When I check the processing in SessionRepositoryMessageInterceptor, I see that it is trying to retrieve the session id through SimpMessageHeaderAccessor that expects the header to contain an object under header key simpSessionAttributes.
Map<String, Object> sessionHeaders = SimpMessageHeaderAccessor
.getSessionAttributes(message.getHeaders());
String sessionId = sessionHeaders == null ? null
: (String) sessionHeaders.get(SPRING_SESSION_ID_ATTR_NAME);
All the attributes that SimpMessageHeaderAccessor seems to expect are not present in the stomp client and just seem to belong to a different protocol.
How do I deal with activating a session under Stomp, Spring WebSocket, Spring Security and Spring Session? Or more specifically:
Why does SessionRepositoryMessageInterceptor use SimpleHeaderAccessor in stead of StompHeaderAcessor?
What headers do I need to pass from a javascript client to create a session (assuming I received the session id through traditional login)?
I don't know what the issue is but I can explain a few things to help you debug the issue.
Spring supports WebSocket-scoped attributes. Those are attributes that exist for as long as the session exists. The SessionRepositoryMessageInterceptor, as a HandshakeInterceptor, hooks into the initial HTTP handshake request and saves the SPRING.SESSION.ID as a WebSocket-scoped attribute. Then after the handshake, when STOMP messages start to flow, it intercepts every incoming message, and retrieves the SPRING.SESSION.ID in the websocket attributes. So I am not sure why you're trying to pass SPRING.SESSION.ID as a header. That's all managed for you as I just explained and associated with the WebSocket session.
As for the question about SimpHeaderAccessor vs StompHeaderAcessor, the former is a more generalized version. It's not wrong to use it as long it gives you enough information. In this case Spring Session doesn't care for STOMP specific details.
I don't understand your second question about what headers need to be passed from a javascript client to create a session. As long as the HTTP handshake is made within the same HTTP session it should just work. There is nothing different here from how you would do any HTTP call.

Grails Rest Client Builder POST Return Error/Exception

I've been working with the grails plugin: 'grails-rest-client-builder:2.0.1'
https://github.com/grails-plugins/grails-rest-client-builder/
I'm experiencing an odd issue when I POST some data to a web service, a 500 Exception, even though the POST indeed is working successfully.
Class
java.lang.NoClassDefFoundError
Message
org/springframework/util/StreamUtils
Around line 195 of PageFragmentCachingFilter.java
if (CollectionUtils.isEmpty(cacheOperations)) {
log.debug("No cacheable annotation found for {}:{} {}"
new Object[] { request.getMethod(), request.getRequestURI(), getContext() });
chain.doFilter(request, response);
return;
}
The response that is coming back from the web service should look like this:
{"id":"9999","key":"IX-2247","self":"https://jira.xxxx.com/rest/api/latest/issue/9999"}
Again, the web service is correctly getting the values that I pass into it, and I verified this by checking the application that I'm posting to and I do see what I expect. Not only that, but I also receive an email from the system that I am POSTing to, and the email contains the correct values from the Grails application.
Here's the POST that I'm using:
def rest = new grails.plugins.rest.client.RestBuilder()
def resp = rest.post("https://jira.xxxx.com/rest/api/latest/issue/"){
auth "Basic xxxx"
contentType "application/json"
json builder.toPrettyString()
}
My hypothesis is that perhaps the issue is that the rest-client-builder is having some kind of issue with the response that is being returned from the web service.
Has anyone encountered anything like this before, where the service is working, but Grails throws a 500 error, even on a successful POST?
Please let me know if I need to provide additional information.
Thanks in advance!
Thank you all for the replies. I ended up upgrading my Grails application to 2.3.5, from 2.2.3 and now the code (above) works perfectly. The 500 error disappeared completely.

How to use REST assured?

I have never used JUnit or other testing frameworks. All i know is how to develop rest service. I recently saw REST assured framework to test REST api. But all the articles that i found looks like below. But i don't know how to pass request xml and how will i get response and when should i call this method.?
Do i need to use some other tool before this REST assured.? I am completely beginner in this kind of testing frameworks. Please show me some light in this world. All i know is how to send request and check values in the response in SOAPUI. I have never tried this.
expect().
statusCode(200).
body(
"user.email", equalTo("test#hascode.com"),
"user.firstName", equalTo("Tim"),
"user.lastName", equalTo("Testerman"),
"user.id", equalTo("1")).
when().
get("/service/single-user/xml");
expect() /* what u expect after sending a request to REST Service */
statusCode(200) /*you are expecting 200 as statuscode which tells request handled successfully at server */
body()
/* the conditions given in body are compare the value with expected values. "equalTo" hamcrest matcher condition (you need to have hamcrest jar in java classpath).*/
when(). /* as is name says above all will be done after sending get/post/put/delete request right so before you put these get,post,put,delete you will have this method as prefix */
get("/service/single-user/xml")
/* the actual REST API request url goes here. can be GET/POST/PUT/DELETE. the confusion for you is its only showing half part which is base path.you can give entire request url in get() method.*/
more on:
http://rest-assured.googlecode.com/svn/tags/1.8.1/apidocs/com/jayway/restassured/RestAssured.html
I hope this helps.

Thinktecture.Identity SAML token unauthorized

I am using the Thinktecture.IdentityModel 4.0 samples for WebApiSecurity. I've modified the AdfsSamlClient to use our ADFS Server. I am able to get a SAML token from out ADFS Server using
var channel = factory.CreateChannel();
var token = channel.Issue(rst) as GenericXmlSecurityToken;
Then I try to make the service call
var client = new HttpClient { BaseAddress = _baseAddress };
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("AdfsSaml", saml);
var response = client.GetAsync("identity").Result;
And get a 401 - Not Authorized call.
I am not sure how to debug this. I have tracing for Microsoft.IdentityModel, but it is only information level trace, no errors or warnings, and nothing I am able to use to debug.
The interesting part of the service trace:
1.
Description OnEndRequest is redirection to IdentityProvider '/WebHost/api/identity'
2.
Description CreateSignInRequest
BaseUri https://[ADFS...]/adfs/ls/
wa wsignin1.0
wtrealm https://[WorkStation...]/WebHost/
wctx rm=0&id=passive&ru=%2fWebHost%2fapi%2fidentity
3.
Description Redirecting to IdentityProvider: 'https://[ADFS...]/adfs/ls/?wa=wsignin1.0&wtrealm=https%3a%2f%2f[WorkStation...]%2fWebHost%2f&wctx=rm%3d0%26id%3dpassive%26ru%3d%252fWebHost%252fapi%252fidentity&wct=2013-09-30T17%3a35%3a04Z'
Thanks for any insight.
Main thing that springs to mind is to make sure the server knows how to handle the "AdfsSaml" scheme that you're using, so you'll want to make sure that your mapping is correct to your token handler.
One thing I tried was to create my own token handler, and mapped that as the token handler for the header. If you want, you can start with Thinktecture's own HttpSamlSecurityTokenHandler, and debug your way through that. Obviously, if it never hits it, then you've got a mapping issue somewhere.
I also found that if an exception was thrown in the ClaimsAuthenticationManager, it would report as unauthorized - even though the exception being thrown was something completely unrelated (in my case, an InvalidCastException). That stumped me for a while, because I hadn't realise that authentication had gotten so far down the pipeline and that validation of the token had actually been successful - I was just checking the HTTP response, which kept saying unauthorised - so make sure you're not being misled by anything trivial like that.

Resources