ReactiveKafkaConsumerTemplate IntegrationTest - spring-boot

I used ReactiveKafkaConsumerTemplate in my project and trying to write some tests for this, I am not understanding how can I achieve this. Looking for examples or documentation on this
my consumer code is like below so I am trying to add a test for consume() so that I can test all the steps filter, process, retry, error
class KafkaConsumerService():CommandLineRunner{
fun consume(): Flux<ReceiverRecord<String,Y>> {
return kafkaConsumerTemplate.receive()
.filter { ***}
.doOnNext { receiverRecord -> process(receiverRecord) }
.retryWhen{}
.doOnError{}
}
override fun run(vararg args: String) {
consume().subscribe()
}
}

Related

near-sdk-rs: view call fails trying to call to attached_deposit, but nothing in the contract seems to be looking at the attached_deposit

I have the following method in my contract:
#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)]
pub struct MyContract {
...,
}
#[near_bindgen]
impl MyContract {
...
pub fn is_account_whitelisted(account_id: &AccountId) -> bool {
Self::account_task_ordinals_map().contains_key(account_id)
}
fn account_task_ordinals_map() -> LookupMap<AccountId, Option<u32>> {
LookupMap::new(b"o".to_vec())
}
...
}
is_account_whitelisted is intended to be used as a view method. I then later use it from near-api-js in the following way:
window.contract = await near.loadContract(nearConfig.contractName, {
viewMethods: ['is_account_whitelisted', ...],
changeMethods: [...],
sender: window.walletAccount.getAccountId()
});
...
window.contract.is_account_whitelisted({'account_id': window.walletAccount.getAccountId()}).then(m => console.log(m));
and it fails with
...
FunctionCallError(HostError(ProhibitedInView { method_name: "attached_deposit" })).
{
"error": "wasm execution failed with error: FunctionCallError(HostError(ProhibitedInView { method_name: \"attached_deposit\" }))",
...
Do I need to annotate the method in some way, am I not calling it right, or is there something that I use in the method that causes the call to the attached_deposit?
Thanks to the Evgeny's comment, I found out that presently a method is only considered a view method if it has a immutable self as the first argument. Here's the link to the relevant code in near-sdk-rs:
https://github.com/near/near-sdk-rs/blob/18b8f8f3b672bfb422ff83a5138395f7e24dd70d/near-sdk-core/src/info_extractor/attr_sig_info.rs#L109
It is likely to be fixed soon, but in the meantime the way to address it is to add the immutable self as the first argument.

How replace create java Thread by Kotlin's coroutines?

I'm a new in Kotlin's coroutines.
Here code with classic Thread:
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import okhttp3.*
import okio.ByteString
import org.slf4j.LoggerFactory
import java.util.concurrent.atomic.AtomicInteger
object BithumbSocketListener : WebSocketListener() {
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
super.onFailure(webSocket, t, response)
Thread {
оkHttpClient.newWebSocket(wsRequest, BithumbSocketListener)
}.start()
}
override fun onMessage(webSocket: WebSocket, text: String) {
super.onMessage(webSocket, text)
logger.debug("ws_onMessage: text = $text")
}
}
fun main(args: Array<String>) {
currenciesList = currencies.split(",")
currenciesList.forEach {
OkHttpClient().newWebSocket(wsRequest, BithumbSocketListener)
}
}
As you can see I have list of currencies (currenciesList). I iterate it and call newWebSocket for every item of list. As you can see BithumbSocketListener is a singleton.
If has some problem with web socket then call callback method onFailure and I create new web socket in separate java thread:
Thread {
оkHttpClient.newWebSocket(wsRequest, BithumbSocketListener)
}.start()
Nice. It's work fine.
But I want replace this code by Kotlin coroutines.
How I can do this?
Thanks.
Since you're processing an async stream of messages, you should port it to coroutines by implementing an actor, such as
val wsActor: SendChannel<String> = actor {
for (msg in channel) {
logger.info("Another message is in: ${msg}")
}
}
From the type of wsActor you can see you're supposed to send messages to it. This is where the bridging code comes in:
class BithumbSocketListener(
private val chan: Channel<String>
) : WebSocketListener() {
override fun onMessage(webSocket: WebSocket, text: String) {
chan.send(text)
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
оkHttpClient.newWebSocket(wsRequest, this)
}
}
Note that, compared to your code, I don't start any new threads for retrying. This has nothing to do with porting to coroutines, your code doesn't need it either. newWebSocket is an async call that returns immediately.
Finally, start the websockets for each currency:
currenciesList.forEach {
OkHttpClient().newWebSocket(wsRequest, BithumbSocketListener(wsActor)
}

Log Spring webflux types - Mono and Flux

I am new to spring 5.
1) How I can log the method params which are Mono and flux type without blocking them?
2) How to map Models at API layer to Business object at service layer using Map-struct?
Edit 1:
I have this imperative code which I am trying to convert into a reactive code. It has compilation issue at the moment due to introduction of Mono in the argument.
public Mono<UserContactsBO> getUserContacts(Mono<LoginBO> loginBOMono)
{
LOGGER.info("Get contact info for login: {}, and client: {}", loginId, clientId);
if (StringUtils.isAllEmpty(loginId, clientId)) {
LOGGER.error(ErrorCodes.LOGIN_ID_CLIENT_ID_NULL.getDescription());
throw new ServiceValidationException(
ErrorCodes.LOGIN_ID_CLIENT_ID_NULL.getErrorCode(),
ErrorCodes.LOGIN_ID_CLIENT_ID_NULL.getDescription());
}
if (!loginId.equals(clientId)) {
if (authorizationFeignClient.validateManagerClientAccess(new LoginDTO(loginId, clientId))) {
loginId = clientId;
} else {
LOGGER.error(ErrorCodes.LOGIN_ID_VALIDATION_ERROR.getDescription());
throw new AuthorizationException(
ErrorCodes.LOGIN_ID_VALIDATION_ERROR.getErrorCode(),
ErrorCodes.LOGIN_ID_VALIDATION_ERROR.getDescription());
}
}
UserContactDetailEntity userContactDetail = userContactRepository.findByLoginId(loginId);
LOGGER.debug("contact info returned from DB{}", userContactDetail);
//mapstruct to map entity to BO
return contactMapper.userEntityToUserContactBo(userContactDetail);
}
You can try like this.
If you want to add logs you may use .map and add logs there. if filters are not passed it will return empty you can get it with swichifempty
loginBOMono.filter(loginBO -> !StringUtils.isAllEmpty(loginId, clientId))
.filter(loginBOMono1 -> loginBOMono.loginId.equals(clientId))
.filter(loginBOMono1 -> authorizationFeignClient.validateManagerClientAccess(new LoginDTO(loginId, clientId)))
.map(loginBOMono1 -> {
loginBOMono1.loginId = clientId;
return loginBOMono1;
})
.flatMap(o -> {
return userContactRepository.findByLoginId(o.loginId);
})

Gradle issue using file and filter

I am trying to loop over a map, for each key read some property files, use filter to replace some tokens. My issue is, looping happens. At the end, instead of having 5 folders, I've just 1 folder inside config. Do I need to close any resources like file/inputstream before going on to the next?
task copyResByHost(type: Copy) {
java.util.HashMap hostMap = new HashMap();
hostMap.put("devserver01","env_dev.properties");
hostMap.put("devserver02","env_dev.properties");
hostMap.put("devserver03","env_dev.properties");
hostMap.put("devserver04","env_dev.properties");
hostMap.put("devserver05","env_dev.properties");
hostMap.each { key, value ->
from "$projectDir/resources/templates"
into("build/config/${key}")
def myProps = new Properties()
file("$projectDir/resources/properties/${value}").withInputStream {
myProps.load(it);
}
file("$projectDir/resources/properties/${key}.properties").withInputStream {
myProps.load(it);
}
filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: myProps)
}
}
Can you let me know where am I making a mistake which is causing 1 folder only created instead of 5 inside config?
Thanks for your guidance.
from and into were being overwritten everytime causing only 1 folder to be created.
So code should be changed as follows:
hostMap.each { key, value ->
println "Creating configs for $key"
//inputs.dir '$projectDir/resources/templates'
// outputs.dir 'build/config/${key}'
doLast {
copy {
from("$projectDir/resources/templates")
into("build/config/${key}")
def myProps = new Properties()
new File("$projectDir/resources/properties/${value}").withInputStream { stream ->
myProps.load(stream);
}
new File("$projectDir/resources/properties/${key}.properties").withInputStream { stream ->
myProps.load(stream);
}
filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: myProps)
}
}
}
from & into, file stream everything should appear within closure doLast { copy { } }

How to define and call custom methods in build.gradle?

As part of my project, I need to read files from a directory and do some operations all these in build script. For each file, the operation is the same(reading some SQL queries and execute it). I think its a repetitive task and better to write inside a method. Since I'm new to Gradle, I don't know how it should be. Please help.
One approach given below:
ext.myMethod = { param1, param2 ->
// Method body here
}
Note that this gets created for the project scope, ie. globally available for the project, which can be invoked as follows anywhere in the build script using myMethod(p1, p2) which is equivalent to project.myMethod(p1, p2)
The method can be defined under different scopes as well, such as within tasks:
task myTask {
ext.myMethod = { param1, param2 ->
// Method body here
}
doLast {
myMethod(p1, p2) // This will resolve 'myMethod' defined in task
}
}
If you have defined any methods in any other file *.gradle - ext.method() makes it accessible project wide. For example here is a
versioning.gradle
// ext makes method callable project wide
ext.getVersionName = { ->
try {
def branchout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-parse', '--abbrev-ref', 'HEAD'
standardOutput = branchout
}
def branch = branchout.toString().trim()
if (branch.equals("master")) {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'describe', '--tags'
standardOutput = stdout
}
return stdout.toString().trim()
} else {
return branch;
}
}
catch (ignored) {
return null;
}
}
build.gradle
task showVersion << {
// Use inherited method
println 'VersionName: ' + getVersionName()
}
Without ext.method() format , the method will only be available within the *.gradle file it is declared. This is the same with properties.
You can define methods in the following way:
// Define an extra property
ext.srcDirName = 'src/java'
// Define a method
def getSrcDir(project) {
return project.file(srcDirName)
}
You can find more details in gradle documentation Chapter 62. Organizing Build Logic
An example with a root object containing methods.
hg.gradle file:
ext.hg = [
cloneOrPull: { source, dest, branch ->
if (!dest.isDirectory())
hg.clone(source, dest, branch)
else
hg.pull(dest)
hg.update(dest, branch)
},
clone: { source, dest, branch ->
dest.mkdirs()
exec {
commandLine 'hg', 'clone', '--noupdate', source, dest.absolutePath
}
},
pull: { dest ->
exec {
workingDir dest.absolutePath
commandLine 'hg', 'pull'
}
},
]
build.gradle file
apply from: 'hg.gradle'
hg.clone('path/to/repo')
Somehow, maybe because it's five years since the OP, but none of the
ext.someMethod = { foo ->
methodBody
}
approaches are working for me. Instead, a simple function definition seems to be getting the job done in my gradle file:
def retrieveEnvvar(String envvar_name) {
if ( System.getenv(envvar_name) == "" ) {
throw new InvalidUserDataException("\n\n\nPlease specify environment variable ${envvar_name}\n")
} else {
return System.getenv(envvar_name)
}
}
And I call it elsewhere in my script with no prefix, ie retrieveEnvvar("APP_PASSWORD")
This is 2020 so I'm using Gradle 6.1.1.
#ether_joe the top-voted answer by #InvisibleArrow above does work however you must define the method you call before you call it - i.e. earlier in the build.gradle file.
You can see an example here. I have used this approach with Gradle 6.5 and it works.
With Kotlin DSL (build.gradle.kts) you can define regular functions and use them.
It doesn't matter whether you define your function before the call site or after it.
println(generateString())
fun generateString(): String {
return "Black Forest"
}
tasks.create("MyTask") {
println(generateString())
}
If you want to import and use a function from another script, see this answer and this answer.
In my react-native in build.gradle
def func_abc(y){return "abc"+y;}
then
def x = func_abc("y");
If you want to check:
throw new GradleException("x="+x);
or
println "x="+x;

Resources