Spring Integration HTTP inbound adapter method name? - http

Is it possible to map the method name to a header with a int-http:inbound-gateway? for example:
<int-http:inbound-gateway request-channel="requests" reply-channel="replies"
supported-moethds="GET,PUT"
path="/user">
<int-http:header name="requestMethod" expression="#requestMethod"/>
</int-http:inbound-gateway>
<!-- ... -->
<int:header-value-router input-channel="requests" header-name="requestMethod>
<int:mapping value="GET" channel="getUserRequests"/>
<int:mapping value="PUT" channel="addUserRequests"/>
</int:header-value-router>
Furthermore, I see examples that utilize #requestParams, but the javadoc for 2.1 mentions #queryParameters, and I don't see documentation for either of these in the official documentation page. Do you guys know a good resource that describes not only how SpEL parses expressions but what fields are available to use with it? All I can tell is I have headers, payload, #pathVariables, and maybe #requestParams or #queryParams, along with any other #beans I have defined in the current context.
Thanks in advance!

That method is always mapped to a header
... http_requestMethod=POST ...
Message<?> message = messageBuilder
.setHeader(org.springframework.integration.http.HttpHeaders.REQUEST_URL, request.getURI().toString())
.setHeader(org.springframework.integration.http.HttpHeaders.REQUEST_METHOD, request.getMethod().toString())
.setHeader(org.springframework.integration.http.HttpHeaders.USER_PRINCIPAL, servletRequest.getUserPrincipal())
.build();
The javadoc is wrong. The two additional variables are #requestParams and #pathVariables.

Related

Kafka Producer for internal topics with individual configs

One of my topologies generates an internal topic e.g. KSTREAM-AGGREGATE-STATE-STORE-0000000031 (see snipped from below) and for which an internal topic <app-id>KSTREAM-AGGREGATE-STATE-STORE-0000000031-changelog is created.
<...>
Processor: KSTREAM-FLATMAPVALUES-0000000022 (stores: [])
--> KSTREAM-AGGREGATE-0000000032, KSTREAM-FLATMAP-0000000027, KSTREAM-MAP-0000000023, KSTREAM-MAP-0000000025, KSTREAM-MAP-0000000029
<-- KSTREAM-TRANSFORMVALUES-0000000017
Processor: KSTREAM-AGGREGATE-0000000032 (stores: [KSTREAM-AGGREGATE-STATE-STORE-0000000031])
--> KTABLE-TOSTREAM-0000000033
<-- KSTREAM-FLATMAPVALUES-0000000022
Processor: KTABLE-TOSTREAM-0000000033 (stores: [])
--> KSTREAM-PEEK-0000000034
<-- KSTREAM-AGGREGATE-0000000032
<...>
the topology is defined as follows (BusObjKey and BusObj both are Avro Objects with according serdes, TransformBusObj provides the business logic for the aggregation and later mapping)
<...>
KStream<BusObjKey, BusObj> busObjStream = otherBusObjStream
.groupByKey()
.windowedBy(TimeWindows.ofSizeWithNoGrace(Duration.ofMinutes(5)))
.aggregate(BusObj::new,
TransformBusObj::aggregate,
Materialized.with(busObjKeySerde, busObjSerde))
.toStream()
.map(TransformBusObj::map);
<...>
How can I controll the properties used for the producer creating as well sending messages to <app-id>KSTREAM-AGGREGATE-STATE-STORE-0000000031-changelog ? In particular I would need to turn compression on (e.g. config.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "snappy") ). Since I do not want to have compression all over the other producers I wonder of how to achive this in Spring Boot.
If you use the config.put(ProducerConfig.COMPRESSION_TYPE_CONFIG,"snappy"), it will turn on compression for all the producers in the Kafka Streams application. The only workaround I can think of would be to provide your own producer via the overloaded KafkaStreams constructor that accepts a KafkaClientSupplier. In your custom producer, you can inspect the topic name before sending and manually compress the data. Since you're manually compressing the data, I believe you'd also have to provide a custom restore consumer that "knows" to decompress. But I'm not sure this suggestion would even work or would be worth the effort.
HTH,
Bill

GMB - Removal of LocationState object in Business Information API

Google deprecated the old GMB API v4.9 account.locations.get endpoint, and replaced it with Business Information API v1 locations.get.
Code change that affects me is:
Removal of LocationState object. The existing fields have been moved into Metadata.
The new Metadata object does not return the attributes LocationState object contained before. The ones I'm interested in are:
isVerified
isPublished
isSuspended
isDisabled
isDisconnected
etc...
My question is:
How could I get this data without using deprecated endpoints?
Try Verification API getVoiceOfMerchantState
isVerified (verify),
isPublished (hasVoiceOfMerchant=true AND hasBusinessAuthority=true),
isSuspended (complyWithGuidelines),
isDuplicate (resolveOwnershipConflict).
isDisabled & isDisconnected have no equivalent in new API
As far as I can see, based on the link you have sent it is written:
Endpoint URL:
Endpoints for all business information, attributes, categories, chains and locations search are accessible at https://mybusinessbusinessinformation.googleapis.com/v1/ instead of https://mybusiness.googleapis.com/v4/
The path name for locations endpoints has changed from
accounts/accountId/locations/locationId to locations/locationId
Maybe it was better if you could provide the request uri in the previous version so we could help you more precisely. Anyhow, what I tested in the google playground is as follows:
open [https://developers.google.com/oauthplayground]
after setting your clientId and Authorisation stuff, in the Request URI write
https://mybusinessbusinessinformation.googleapis.com/v1/locations/XXXXX?readMask=storeCode,metadata,profile,serviceArea,labels,adWordsLocationExtensions
instead of XXXXX, write your locationId
you can write different readMask fields, The possible fields for readMask are:
play with different fields to check if you have your desired one or not readMask="storeCode,regularHours,name,languageCode,title,phoneNumbers,categories,storefrontAddress,websiteUri,regularHours,specialHours,serviceArea,labels,adWordsLocationExtensions,latlng,openInfo,metadata,profile,relationshipData,moreHours";
If above does not help you, in the link below I see that all metadata attribute of a location might be:
Click [here] (https://developers.google.com/my-business/reference/businessinformation/rest/v1/accounts.locations#Location.Metadata)

LocustIO: How to do batch request

I started to use LocustIO for load testing a 3rd party API which provides a way to do batch requests (http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_BatchRequests).
How can this be done using LocustIO?
I tried with the following:
def batch(self):
response = self.client.request(method="POST", url="/$batch", auth=("ABC", "DEF"), headers={"ContentType": "multipart/mixed; boundary=batch_36522ad7-fc75-4b56-8c71-56071383e77b"}, data="Content-Type: application/http\nContent-Transfer-Encoding: binary\n\nGET putyoururlhere HTTP/1.1\nAccept: application/json\n\n\n")
Auth is something I need to have authentication to the API, but that's not the point of the question and "putyoururlhere" should be replaced with the actual url. Either way, it gives errors when executing the test, so I must be doing something wrong.
People with experience how to do this?
Kind regards!
The data parameter should be your POST body (only), you cant put additional headers in it the way you did. You probably just want to add them as additional entries in the dict you pass as headers
Se the documentation for python requests library for more details. https://requests.readthedocs.io/en/master/

Whats the difference between 'options' and 'overrides' in Rblpapi?

In the documentation here, Bloomberg does not make a distinction in the request. The requests can only have 3 things:securities, fields and overrides.
So what are options? How do they get used? Is this a distinction imposed by Rblpapi? Can someone explain the distinction?
Please let me know if I am incorrectly understanding something.
Options are parameters that change how a Request or Subscription should behave. For example, a ref data request with returnEID=true will return the EID(s) of each security in response messages. A Subscription with interval=5.0 will make it an Intervalized Subscription.
Overrides, on the other hand, are field/value pairs that you specify in Requests to alter the form or content of the returned fields, for example, GICS_SECTOR_NAME will normally return sector name in English (or precisely the default terminal language), you can specify SECURITY_NAME_LANG=9 override to get the name in Korean. You can also "request" SECURITY_NAME_LANG field to know the language used in GICS_SECTOR_NAME field. Overrides can be used in Request/Response only (not subscriptions), and are applied to the entire request, on all fields that react to that override.
option.names = "optName", option.values = "optVal"
in R, maps to:
request.set("optName", optVal);
in Java. E.g:
option.names="periodicitySelection", option.values="MONTHLY")
request.set("periodicitySelection", "MONTHLY");

How can I configure WSO2 to automatically replace API urls?

I have an API running on http://my_internal_api.com, and I'm exposing it with WSO2, on https://mywso2:8280/my_api.
Everything works just fine, but the REST API is giving off url attributes in json that are formatted for the original server url.
Example:
When retrieving contact info, I get a JSON object:
[{contact_id: 1, url: contact_url}, {}]
This contact_url is in the form: http://my_internal_api.com/contacts/1
It should be: https://mywso2:8280/my_api/contacts/1
Is there a way to solve this? I'm guessing a squence should be used, but I don't know if this is the right approach or I'm trying to reinvent the wheel.
You can add an out sequence using mediation extension[1].There find all occurrence of "my_internal_api.com" and replace by "mywso2:8280".For replacing you string in the payload you can use the script mediator.
<script language="js">
var payload = mc.getPayloadXML().toString();
<property name="PAYLOAD" value="payload"/>
var changedPayload = payload.replace(/http:\/\/my_internal_api.com/, mc.getProperty('apiURL'));
var xml = new XML(newPayLoad);
mc.setPayloadXML(xml);</script>
1.https://docs.wso2.com/display/AM180/Adding+Mediation+Extensions
The easiest way is to use a header mediator to add a X-Forwarded-Host header, like this:
<sequence name="WSO2AM--Ext--In">
<header name="X-Forwarded-Host"
scope="transport"
expression="get-property('transport','Host')"/>
<header name="X-Forwarded-Proto" scope="transport" value="https"/>
</sequence>
This way, most APIs will be able to correctly resolve the host

Resources