Set HTTP GET Parameters in Finagle - finagle

In Finagle, how do I create a request an HTTP GET request with parameters in a safe, clean way?
val request = RequestBuilder()
.url("http://www.example.com/test")
.addParameter("key", "value") // this doesn't exist
.buildGet()
request // should be a GET request for http://www.example.com/test?key=value

You can use the confusingly-named Request.queryString:
val request = RequestBuilder()
.url(Request.queryString("http://www.example.com/test", Map("key" -> "value"))
.buildGet()

The arguments passed to RequestBuilder.url() are expected to be fully-formed, so Finagle doesn't provide any way to tack on more query parameters.
One way to solve this would be to construct a URL object outside of the context of the RequestBuilder chain. You could define your query parameters in a Map, turn it into a query string, and then concatenate it to the base URL:
val paramStr = Map("key" -> "value", ...) map { case (k, v) =>
k + '=' + v
} mkString("?", "&", "")
val request = RequestBuilder.safeBuildGet(
RequestBuilder.create()
.url("http://www.example.com/test" + paramsStr)
)
Note that you'll need to encode any query parameters that you specify in the Map.

You can safely create your request by this way:
import java.net.URL
import com.twitter.finagle.http.{Http, RequestBuilder}
val request = RequestBuilder()
.url(new URL("http://www.example.com/test?key=value"))
.setHeader("Content-Type", "application/json") //if you need
.buildGet()

Related

Flux returns unsorted data for StepVerifier

I expect to receive two elements after writing three to the database. The query returns a Flux, which returns the elements unsorted.
#Test
fun `SUCESSFULLY query pending purchases`() {
// arrange
val arrived = TestDataFactory.buchungssatzEntity(
sequentialId = 1,
arrived = true
)
val pending = TestDataFactory.buchungssatzEntity(
sequentialId = 2,
arrived = false
)
val next_pending = TestDataFactory.buchungssatzEntity(
sequentialId = 3,
arrived = false
)
// act
buchhaltungWriter.save(arrived)
buchhaltungWriter.save(pending)
buchhaltungWriter.save(next_pending)
val purchases = inventoryFinder.findAllPendingPurchases()
// assert
StepVerifier.create(purchases)
.expectNext(pending)
.expectNext(next_pending)
.verifyComplete()
}
This always throws
expected value: BuchungssatzEntity(... sequentialId=2 ...); actual value: BuchungssatzEntity(... sequentialId=3 ...)
I do not want to add sorting to the database query, it's a waste of time. How can I test Flux with 'all of these elements but in any order' or should I just go for a Mono in this case, return a list and do the rest myself? Then again, that's not why I'm using reactive.
PS: Goal of this test is to verify that my Spring query language statement filters correctly.
-------- UPDATE
I solved it by using
StepVerifier.create(inventoryFinder.findAllPendingPurchases())
.recordWith { listOf<PurchasesModel>() }
.thenConsumeWhile { i: Any? -> purchases.contains(i) }
.consumeRecordedWith{ }
.verifyComplete()
One way to do that is to use the thenConsumeWhile operator along with expectNextCount. If there is any element in the sequence that doesn't match, the StepVerifier will error.
In Java:
List<Item> pendingItems = List.of(pending, next_pending);
Flux<Item> items = inventoryFinder.findAllPendingPurchases();
StepVerifier.create(items)
.expectNextCount(2) //expecting 2 elements
.verifyComplete();
StepVerifier.create(items)
.thenConsumeWhile((i) -> pendingItems.contains(i)) // check if element was expected
.verifyComplete();

Power Query delayed recursion

I'm very new to Power Query and trying to piece a little demo together in Excel.
I have two web endpoints: I have to post some content to the first endpoint, this gives me the url of the second endpoint and then I have to query this second endpoint for the actual results. The second endpoint gives back a json response and in it, there is a field that represents if the results are ready or not. If the results are ready, they can be processed, if not, the endpoint should be queried again at a later date.
Here's the code I have so far:
let
apikey = "MYAPIKEY",
proxyendpoint = "URL OF THE FIRST ENDPOINT",
bytesbody = File.Contents("FILE TO POST"),
headers = [#"Ocp-Apim-Subscription-Key" = apikey],
bytesresp = Web.Contents(proxyendpoint, [Headers=headers, Content=bytesbody]),
jsonresp = Json.Document(bytesresp),
opLoc = jsonresp[OperationLocation],
getResult = (url) =>
let
linesBody = Web.Contents(url, [Headers=headers]),
linesJson = Json.Document(linesBody),
resultStatus = linesJson[status],
linesData = if (resultStatus = "Succeeded") then
linesJson[recognitionResult][lines]
else
Function.InvokeAfter(()=>#getResult(url),#duration(0,0,0,5))
in
linesData,
linesText = List.Transform(getResult(opLoc), each _[text]),
table = Table.FromList(linesText)
in
table
My problem is that when I check with Fiddler, I see the second endpoint queried once, I can check there in the response that the results are not ready, the data loading "hangs", but I cannot see any additional calls to the second endpoint, so basically my recursive calls are not being evaluated.
What am I doing wrong?
With the ()=> in the first argument of Function.InvokeAfter, the result of Function.InvokeAfter will be the function getResult, rather than the result from getResult. So it should be left out:
Function.InvokeAfter(#getResult(url),#duration(0,0,0,5))
Turns out my code was basically right. The issue was that Web.Contents() does some internal caching, that's why I couldn't see any more calls in Fiddler and that's why my data loading "hang" (since the first time the recursion exit criterion was false and the result got cached, every subsequent recursion just used the same data).
I created some POCs for the delayed recursion scenario and strangely, everything worked. I changed things around until I reached a version of the POC where the only difference was the Web.Contents() call. So I did a search for this specific issue and found a post here.
So as suggested in this post, I added a new header value to every Web.Contents() call to avoid the response being cached (also cleaned up the code a bit):
let
apikey = "MYAPIKEY",
proxyendpoint = "URL OF THE FIRST ENDPOINT",
bytesbody = File.Contents("FILE PATH TO BE POSTED"),
headers = [#"Ocp-Apim-Subscription-Key" = apikey],
bytesresp = Web.Contents(proxyendpoint, [Headers=headers, Content=bytesbody]),
jsonresp = Json.Document(bytesresp),
opLoc = jsonresp[OperationLocation],
getResult = (url, apiKeyParam) =>
let
// note the extra header here, which is different in every call
currentHeaders = [#"Ocp-Apim-Subscription-Key" = apiKeyParam, #"CacheHack" = Number.ToText(Number.Random())],
linesBody = Web.Contents(url, [Headers=currentHeaders]),
linesJson = Json.Document(linesBody),
resultStatus = linesJson[status],
result = if (resultStatus = "Succeeded") then linesJson[recognitionResult][lines]
else Function.InvokeAfter(()=>#getResult(url, apiKeyParam), #duration(0,0,0,5))
in result,
linesText = List.Transform(getResult(opLoc, apikey), each _[text]),
table = Table.FromList(linesText)
in table

Java 8 Streams Filter a list based on a condition

I am trying to extract a filtered list on top of the original list based on some condition. I am using backport version of Java 8 and am not pretty sure how to do this.I get the Set from ccarReport.getCcarReportWorkflowInstances() call. I need to iterate and filter this set based on a condition match( I am comparing the date attribute in each object with the request date being passed. Below is the code
Set<CcarReportWorkflowInstance> ccarReportWorkflowInstanceSet = ccarReport.getCcarReportWorkflowInstances();
List<CcarReportWorkflowInstance> ccarReportWorkflowInstances = StreamSupport.stream(ccarReportWorkflowInstanceSet).filter(ccarReportWorkflowInstance -> DateUtils.isSameDay(cobDate, ccarReportWorkflowInstance.getCobDate()));
The routine which is doing the job
public List<CcarRepWfInstDTO> fetchReportInstances(Long reportId, Date cobDate) {
List<CcarRepWfInstDTO> ccarRepWfInstDTOs = null;
CcarReport ccarReport = validateInstanceSearchParams(reportId, cobDate);
Set<CcarReportWorkflowInstance> ccarReportWorkflowInstanceSet = ccarReport.getCcarReportWorkflowInstances();
List<CcarReportWorkflowInstance> ccarReportWorkflowInstances = StreamSupport.stream(ccarReportWorkflowInstanceSet).filter(ccarReportWorkflowInstance -> DateUtils.isSameDay(cobDate, ccarReportWorkflowInstance.getCobDate()));
ccarRepWfInstDTOs = ccarRepWfInstMapper.ccarRepWfInstsToCcarRepWfInstDTOs(ccarReportWorkflowInstances);
return ccarRepWfInstDTOs;
}
Error I get when I tried to use streams.
Assuming I understood what you are trying to do, you can replace your method body with a single line :
return
validateInstanceSearchParams(reportId, cobDate).getCcarReportWorkflowInstances()
.stream()
.filter(c -> DateUtils.isSameDay(cobDate, c.getCobDate()))
.collect(Collectors.toList());
You can obtain a Stream from the Set by using the stream() method. No need for StreamSupport.stream().
After filtering the Stream, you should collect it into the output List.
I'd use shorter variable and method names. Your code is painful to read.

How to make JDBCTemplate.query() generic

I am new to spring framework.I found this even by looking in documentation but didn't find my desired method. Let me explain thing which I want JDBCTemplate.query() method can take multiple parameters which can be 2, 3 ,4....n.Now I am trying to find a method [if JDBTemplate have] through which i just passed a object/array/list , mean a generic parameter so I get rid from the multiple methods.As If I have 200 stored procedures then I have to write 200 mehods! huhCurrently I am doing this by passing an array and splitting it at DB end but I want to find a good way.Any idea/suggestions
Are you looking for something like this?
//set any number of parameters
Object[] parameters = new Object[] { new Integer(1), "test" };
String sqlQuery = "select * from table1 t where t.id = ? and t.text = ?";
SqlRowSet srs = getJdbcTemplate().queryForRowSet(sqlQuery , parameters);
You may generalize the is by passing the query and parameters from outside of the method as an argument.

Django - JSON response with serialized object

I am trying to send a serialized object using JSON. Here is my view code:
if request.is_ajax():
resp = {}
if request.POST:
if form.is_valid():
g = form.save()
resp['graph'] = serializers.serialize('json', [g, ])
resp['success'] = True
else:
resp['errors'] = form.errors
resp['success'] = False
return HttpResponse(simplejson.dumps(resp), mimetype='application/javascript')
return render(request, 'graph/inlines/create.html', {'form':form})
The problem is (rather obviously) that the 'graph' object I am trying to return is being serialized twice (once with serializers.serialize and again when I used simplejson.dumps) and the object is being received as a json string.
I tried just doing this:
resp['graph'] = g
But it throws a server error as the object obviously isn't serialized when I try to use simplejson.dumps.
Is there a way I can tell it to ignore this key when dumping the data? Would appreciate any help.
Rather than serializing the graph queryset to json the first time, use serializers.serialize('python', g) to convert it to a Python dictionary first. Then the whole thing will be converted to json at the end.

Resources