I have the below use case.
Request is received by the ws-inbound gateway of service1.
Service1 Passes the request to another ws-outbound gateway service2
Service2 ws inbound gateway has an interceptor configured, which adds a custom soap header to the response
the response from service 2 is passed to the output channel of service 1 (Final response).
I am able to see that soap header is added by printing the soap envelope in interceptor (service2), but it is not present in the final response. Any pointers to solve this issue will be helpful
The <int-ws:outbound-gateway> uses DefaultSoapHeaderMapper by default.
And its logic to populate source.getSoapAction(); and source.getSoapHeader();. But for that purpose you should configure mapped-reply-headers for your desired headers on the <int-ws:outbound-gateway>.
Related
I have API 1 which is defined by int-http:inbound-gateway and has service activator to perform some business logic and sends output on output channel same as reply channel of the inbound gateway(simple flow)
I also have API 2 which is defined in different xml file which also has int-http:inbound-gateway and int-http:outbound-gateway which performs on its own.
Now I want to call API 2 from API 1 but I don’t want to send message of the output channel of first API 1 to API 2, API 1 output channel response if for the end user to consume!
If I use request channel of the API 2 as output channel of API 1, I am thinking I will lose the output of the API 1.
Would you please help how this can be achieved?
Edit :
API 1(there is no need of outbound gateway as this API is doing db operations)
<int-http:inbound-gateway
request-channel="aRequestInputChannel"
reply-channel="aOutputChannel"
supported-methods="POST"
path="/perform"
mapped-request-headers="*"
request-payload-type="com.test.spring.integration.LPRequestPayload">
<int-http:request-mapping consumes="application/json" />
</int-http:inbound-gateway>
<int:service-activator input-channel="aRequestInputChannel" ref="IBAdapterController" method="attachData" output-channel="unRequestChannel"/>
API 2:
<int-http:inbound-gateway
request-channel="unRequestChannel"
reply-channel="unResponseChannel"
supported-methods="POST"
path="/test/unOp"
request-payload-type="com.test.spring.integration.LPRequestPayload"
mapped-request-headers="userId, userName, languageCode, HTTP_REQUEST_HEADERS" >
<int-http:request-mapping consumes="application/json,application/xml" />
<int-http:header name="userId" expression="#requestParams[userId]"/>
</int-http:inbound-gateway>
<int:service-activator input-channel="unRequestChannel" output-channel="unOutputChannel" ref="unAdapterController" method="getUnOpDetails" />
so here if I use output-channel="unRequestChannel" of first api as request channel of API 2,
I am loosing original payload as I am sending http response entity from the controller of the first api. I will need to send LPRequestPayload from first api which is not the requirement. as I am performing some db operation if first api, I need to send its response to the end user.
API 2 is like some mandatory operation that needs to be done after db operation is done.
You need to provide more info about your configuration and use-case.
It is not clear if you are going to call API instead of just replying from the service activator or in addition.
You may also learn that there is no need in the reply-channel in the inbound gateways and output-channel in the last in the flow endpoint. An inbound gateway always populates a replyChannel header and an endpoint (e.g. service activator) without an output-channel is going to produce its reply message exactly into that replyChannel from headers. So, it it might be possible that your requirements are met very easy:
inbound gateway 1 > request channel 1 -> service activator -> request channel 2
inbound gateway 2 > request channel 2 -> outbound gateway 2
With this configuration it doesn't matter if you have that inbound gateway 2 or not, the outbound gateway 2 is always going to reply to the replyChannel header from a request message. Therefore in your case when you initiate request from the inbound gateway 1, the outbound gateway 2 is going to reply back to that one. If you request via inbound gateway 2, then reply will come back exactly into this request initiator. The Reply Address pattern with its power.
Update
The link below is used to request token and refresh token depending on a field in the body:
http://example.com/token
1 Request a token
A field in the body: grant_type:password
Steps:
1 When the request arrives, APIM forwards it to 3rd party
2 Once APIM receives the reponse from 3rd party, it returns the result to its client.
We want to log data (url, response status code) for this url to Table Storage. Requet for the same url is not logged below:
2 Refresh the token
A field in the body: grant_type:refresh_token
Application Insight is used with APIM, I wonder if Table Storage is the best tool.
Is there built-in UI that is available for viewing data stored in Table Storage
Any information or link or code sample would be appreciated.
C#
VS 2017
APIM has a few ways to send data out of request processing pipeline:
send-request/send-one-way-request allows you to send an HTTP request, you're in charge of constructing request in HTTP terms: method, URL, headers, body.
log-to-eventhub allows you to send a message to EH. You can specify C# expression that produces message payload.
AppInsights integration will allow you to record client request, backend request, backend response, and client response for each request processed by APIM. You can configure it to log extra headers and part of body.
Context : I have inbound gateway which receives http request over json, which then goes to internal gateway, filtered and transformed , and sent to chain of http outbound gateway calls ( 4 calls ) and after 4 calls are complete, response is sent back to inbound gateway to send a response to client.
External System ( client ) calls > http Inbound gateway --> IFlow ( internal gateway #messaging gateway ) --> filters- transforms - > http outbound gateway --> External system ( api to retrieve data ).
between transform and http outbound gateway - there are 4 http calls over rest i.e. i call 4 external endpoints to get right data and send back to Client.
inbound gateway transforms json to model object at IFlow. lets say model object is CallModel.
At this point, i want to store this model object because later, i transforms the headers and payload for specific endpoints and if any extra header is there in request, external system throw error ( 409 and etc), therefore i cannot keep values in headers for calling http outbound gateway.
Is it possible to store CallModel or values from it, and not to propogate them for 3 successive http outbound gateway calls , and then at 4th call, i get CallModel and use values from it for 4th calls.
I thought about using a cache or creating a class to store, but perhaps there is a cleaner way.
I have one inbound gateway which receives messages over Rest. All messages recieved enter to Internal Gateway . Below is the inbound gateway xml file.
<bean name="testConfig" class="test.TestApiConfiguration"/>
<context:annotation-config/>
<int-http:inbound-gateway request-channel="requestChannel" supported-methods="POST" path="/data" reply-channel="replyChannel"
request-payload-type="com.test.model.CallFlow" header-mapper="cc20InBoundHeaders" error-channel="errorChannel" reply-timeout="9000">
<int-http:request-mapping produces="application/json" consumes="application/json"/>
</int-http:inbound-gateway>
<bean id="cc20InBoundHeaders" class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
<property name="inboundHeaderNames" value="*"/>
</bean>
<bean id="cc20OutBoundHeaders" class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
<property name="outboundHeaderNames" value="Content-Type, HTTP_REQUEST_HEADERS"/>
<property name="userDefinedHeaderPrefix" value="" />
</bean>
So, inbound gateway messages arrive as Json correctly and then an Internal Gateway accepts them and messages are passed into channels are per the configuration.
#MessagingGateway(name="callFlowGateway", requestChannel = "callFlowRequestChannel")
public interface ICallFlow {
/**
* Process CallFlow Request
* #param message SI Message covering APiCall payload and relevant headers for service
*/
#Gateway
void processCallFlowRequest(Message<CallFlow> message);
}
Till here, it works as expected. Messages flow to Filter and then router. in Router, if type of one json property is "drink" service, then drink channel is invoked and relevant outbound gateways are called to request an external API endpoints over REST.
But before calling each of the rest endpoints of that external API, you need to have a valid session id token to access other endpoints. It returns a session id in its payload to call other endpoints Beside that, it takes application/x-www-form-urlencoded as content Type in header.
I created a transformer to create request for authentication service.
#MessageEndpoint
public class AuthenticateTransformer {
#Transformer(inputChannel = "splitterChannel", outputChannel = "authenticateRequestChannel")
public Message<?> transform(CallFlow callFlow) {
Map<String, Object> messagePayload = new HashMap<String, Object>();
messagePayload.put("user", "test");
messagePayload.put("password", "test");
return MessageBuilder.withPayload(messagePayload).setHeader("Content-Type", "application/x-www-form-urlencoded").build();
}
}
So, ideally , a call comes to inbound gateway-
Json is converted to an internal object. Based on one property value in JSON, i call different external rest endpoints using http outbound gateway.
Since the call for authentication to get session id is not in Json that is received, i have to create an order in the flow.
I need to invoke an http outbound gateway for authentication to get that session id. How can i invoke this outbound from inbound gateway because that should be executed before every call to other endpoint.
After i get that session id , then i want other endpoints over Rest, at this phase, i want ICallFlow gateway to be called , so that based on value in json, and that session id from step 1, i can call other rest endpoints and get response back.
So, i am stuck in passing that session id token from First call to the second call ? plus i want ICallFlow only be invoked after first authentication request is complete , and pass that session into other subsequent requests. I read that header enricher can do that, where i can put payload into headers, but somehow its not working. Also, i am not sure how to create above flow in the right order.
Any help would be highly appreciated.
You that's too much information in a single thread and it somehow confusing and misleading.
What I can suggest you is something like ContentEnricher: https://docs.spring.io/spring-integration/docs/5.0.1.RELEASE/reference/html/messaging-transformation-chapter.html#payload-enricher
So, you will call that auth service via request-channel sub-flow, get a session id back and will be able to populate it into headers or that ICallFlow payload if that is possible.
you should be careful using MessageBuilder in the #Transformer use-case. That one doesn't merge request headers afterwards and you won't be able to bring a response to the <int-http:inbound-gateway> in the beginning, just because the replyChannel header will be lost.
The way to carry request headers is like accept a Message in the transform() method and call copyHeaders() on the MessageBuilder.
So, I've heard about request validator in API gateway.
Is it possible to validate request if it has atleast 1 parameter/querystring?
Example: Either name or id should be in the query string
https://something.domain.com/dev/employee?name=myname
https://something.domain.com/dev/employee?id=myid
Basically, what I want is that before a Lambda function is executed, this should consider these conditions first
SHOULD have a parameter
Either a name or an id should be in that parameter
API Gateway can perform the basic validation. For the basic validation, API Gateway verifies either or both of the following conditions:
The required request parameters in the URI, query string, and headers of an incoming request are included and non-blank.
The applicable request payload adheres to the configured JSON-Schema request model of the method.
To enable basic validation, you specify validation rules in a request validator, add the validator to the API's map of request validators, and assign the validator to individual API methods.
Please read documentation here