Limiting the scope of a transaction in Apache Camel - scope

I have a transacted Camel route with a number of processors
from(Constant.RouteA)
.transacted()
.process(processor1)
.process(processor2)
.process(processor3)
.wireTap(Constant.RouteB)
.wireTap(Constant.RouteC)
.end()
My problem is that I don't want the final part of the route (the wiretaps) to be part of the transaction i.e. I want them to be executed once processor3 has finished and the transaction committed.
Initially I looked at using onCompletion() but it doesn't seem to work together with transacted().
So I found another way which requires using policy() to limit the transaction scope i.e.
from(Constant.RouteA)
.policy("PROPAGATION_REQUIRED")
.process(processor1)
.process(processor2)
.process(processor3)
.end()
.wireTap(Constant.RouteB)
.wireTap(Constant.RouteC)
.end()
The problem is that this solution requires to define the SpringTransactionPolicy in the Spring configuration, but the software I'm working on doesn't use Spring. Transactions are managed by Bitronix and everything works just by using the transacted() method, which as far as I can tell doesn't allow you to limit the scope of a transaction.
Is there a simple way to achieve my goal? Hopefully without bringing Spring into the picture. Thank you!

Try to create two routes. For example:
from(direct:startRoute)
.to(Constant.RouteA)
.wireTap(Constant.RouteB)
.wireTap(Constant.RouteC);
from(Constant.RouteA)
.transacted()
.process(processor1)
.process(processor2)
.process(processor3);
Once route "Constant.RouteA" is finished all changes will committed.

Related

Passing data from one step to another using screenplay ( e.g. When -> Then )

Using serenity-js, with cucumber and screenplay, i can't get to pass data from one step to another. E.g. : a "When" step defined by a pretty user.attempsTo() that simply calls a webservice, and a "Then" step that should simply checks the response of the webservice. "TakeNote" forgets the data of the previous step ( as i could see, even surprising) and "LastResponse" context might be lost also...
I guess there is a simple way to store an object (as a Question maybe) in one Activity of the "When" step, and get back this object in an Activity of the "Then" step.
Without Serenity, i would use a World object that is clearly a simple way to do the job, but i'm sure there a Serenity pretty way to do the trick.
Thank you.
Bruno
I tried to pass the object with LastResponse, with TakeNotes. But the object seems to be lost.
I found what was wrong (answering to myself).
user.attempsTo() is actually processed prior to the next step only if a resolution of the promise is asked, so if preceded by return, or await, or if it is declared as an implicit return using arrow function like this ( user :Actor) => attempsTo(...) ).
Without the promise resolution, interactions are not executed in the described sequence, and this is really no good.
The symptom for a bad code is that the interactions are not logged in their steps, but in step further. Hope this helps.

Jooq database/schema name mapping

I use jooq to generate objects against a local database, but when running "for real" later in production the actual databases will have different names. To remedy this I use the <outputSchemaToDefault>true</outputSchemaToDefault> config option (maven).
At the same time, we have multiple databases (schemas), and are using a connection pool to the server like "jdbc:mysql://localhost:3306/" (without specifying a database here).
How do I tell jooq which database to use when running queries?
I have tried all config I can think of:
new Settings()
.withRenderSchema(true) // true/false seems to make no difference.
.withRenderCatalog(true) // true/false seems to make no difference.
.withRenderMapping(new RenderMapping()
.withDefaultSchema("my_database") // Seems to have no effect.
// The above 3 configs always give me an error saying "no database selected".
// Adding this gives me 'my_database.my_table' does not exist - while it actually does.
.withSchemata(new MappedSchema()
.withInputExpression(Pattern.compile(".*"))
.withOutput("my_database")
));
I have also tried using a database/schema name, as in not configuring outputSchemaToDefault. But then, adding the MappedSchema code above, but that gives me errors with "'my_databasemy_database.my_table' does not exist", which is correct. I have no clue why that code gives me the database/schema name twice?
Edit:
When jooq tells me that the db.table does not exist, if I put a break point in a good place and get the sql from jooq and run exactly that against my database it does work. But jooq fails to run it.
Also, I'm using version 3.15.3 of jooq.
I solved it. Instead of using .withInputExpression(Pattern.compile(".*")), it seems to work with .withInput("").
I'm still not sure why it works, or if this is the "correct" way of solving it. But at least it is a way forward.
No clue why using the pattern, I got the name twice though. But that one I'll leave alone.

Azure Function Route Parameter Reading: context.bindingData.paramName vs context.req.params.paramName

I have a route definition in function.json: entity/{paramName}
When I make a GET request: http://localhost:7071/api/entity/50043e-315
In context.bindingData.paramName I get surprising 5.0043e-311, while context.req.params.paramName contains 50043e-315.
I noticed that here both ways of reading can be used; and here the same is meant, though the links are dead by now, while the example here mentions only context.bindingData.
Question: What is more preferable? And what is the difference?
I believe the problem here is that the somewhere (if I were to make a guess, here) the param is being parsed as a double before being stored as binding data. But when fetching it from the request object, it is fetched as a string from the URL directly. Hence the difference.
I believe there are only a few cases where this might happen and this is one of them.

Jmeter ${__setProperty()} Not working across multiple threads in the same thread group

I am trying to do setproperty across multiple threads in the same threadgroup, the postprocessor set new variable using setproperty, so that It can be accessed across multiple threads.
In Beanshell preprocessor, I'm having below line of code.
${__setProperty("url", "youtube")};
Under thread Group I'm having Beanshell post processor, having below one line in postprocessor.
${__setProperty("url", "google")};
under thread group, I have Http Sampler, in hostname field I have given ${__property(url)}.com
The Aim is, when it executes first time, the URL will be google.com and when first threads complete than
the URL becomes youtube.com
But the setProperty only set google, and the second one in postprocessor was not working.
Refer the below Image for details, it shows how I created the element in Jmeter.
enter image description here
Note: This was just a sample use case, but I have complex example, but answering to this question will help me to add the logic in complex script.
Thanks
So is the goal that the very first thread to complete will change the URL for all subsequently created threads?
My understanding of the documentation is that you can't change the value of a property inside the thread-group:
Properties can be referenced in test plans - see Functions - read a property - but cannot be used for thread-specific values.
(see http://jmeter.apache.org/usermanual/test_plan.html#properties)
My assumption is that each thread in a thread-group gets a copy of the properties. If you change the value of the property inside the thread group, then you are actually changing the copy for that particular thread. Since you are changing it in the post-processor, the thread is very likely just about to be disposed, resulting in your change being lost. After disposal a new thread is created but with the original value of the property.
So what you need to do is figure out how to change the value outside of the thread-group.
I have done something similar in my own tests whereby I am changing the value of a property in the middle of the test, and the value is picked up immediately by all of the active thread-groups, resulting in each new thread created from that point forward getting the new value. I am doing this by using the Beanshell Server: https://jmeter.apache.org/usermanual/best-practices.html#beanshell_server
In my specific case I use jenkins job that calls a shell-script which connects to the beanshell-service running on the local-host:
java -jar ${jmeter_home}/apache-jmeter-5.0/lib/bshclient.jar localhost 9000 ${test_plan_home}/update_Prop.bsh "${property}" "${value}"
where my update_prop.bash file is simply:
import org.apache.jmeter.util.JMeterUtils;
JMeterUtils.getJMeterProperties().setProperty(args[0],args[1]);
You would not need to use Jenkins or anything like that, though - if you setup your JMeter Process to include the Beanshell-server (see the link above) then you can simply replace the code in your post-processor:
${__setProperty("url", "google")};
with the code to connect to the beanshell server and execute that command there instead:
exec("./updateprop.bash url google");
JMeter properties are global therefore once you set the property it is available for all threads
Each JMeter thread (virtual user) executes Samplers. Pre and Post processors are obeying JMeter Scoping Rules Looking into your test plan the execution order is following:
Beanshell PreProcessor
HTTP Request Sampler
Beanshell PostProcessor
therefore HTTP Request sampler will never hit youtube (unless you run into a race condition due to concurrency) because PreProcessor will set the URL back to google
It is recommended to use JSR223 Test Elements and Groovy language for scripting since JMeter 3.1
It is NOT recommended to inline JMeter Functions and/or variables into scripts, you need to either use "Parameters" section or go for code-based equivalents instead so you need to replace this line:
${__setProperty("url", "youtube")};
with this one:
props.put("url", "youtube");

restify.js route endpoint conflict with parameter

My code is like below:
server.get('/currency/:code', currency.find);
server.get('/currency/rates', currency.rate_getall);
Whenever I try to reach [/rates] endpoint, the server will assume I am passing parameter to '/currency/:code' route. How can I fix this? Thank you.
Ryan
If you can I would consider changing up your rest interface just a little.
server.get('/currency/:code', currency.find);
server.get('/currency/rates/:type', currency.rate);
That way it solves your initial problem and allows for flexibility in the future if you just want to return a rate for a particular currency.
Inside your currency.rate function you could check for either an id or the literal 'all' and return what is appropriate.

Resources