How to use delayElements() with Flux merge? - spring-webflux

I am following a tutorial and I believe my code is same with the instructor's one but I did not understand why delayElements() is not working.
Here is the caller method:
public static void main(String[] args) {
FluxAndMonoGeneratorService fluxAndMonoGeneratorService = new FluxAndMonoGeneratorService();
fluxAndMonoGeneratorService.explore_merge()
.doOnComplete(() -> System.out.println("Completed !"))
.onErrorReturn("asdasd")
.subscribe(System.out::println);
}
If I write the method without delay elements as:
public Flux<String> explore_merge() {
Flux<String> abcFlux = Flux.just("A", "B", "C");
Flux<String> defFlux = Flux.just("D", "E", "F");
return Flux.merge(abcFlux, defFlux);
}
Then the output in the console is(as expected):
00:53:19.443 [main] DEBUG reactor.util.Loggers$LoggerFactory - Using Slf4j logging framework
A
B
C
D
E
F
Completed !
BUILD SUCCESSFUL in 1s
But I want to use delayElements() to test merge() method as:
public Flux<String> explore_merge() {
Flux<String> abcFlux = Flux.just("A", "B", "C").delayElements(Duration.ofMillis(151));
Flux<String> defFlux = Flux.just("D", "E", "F").delayElements(Duration.ofMillis(100));
return Flux.merge(abcFlux, defFlux);
}
And nothing happens, not onComplete nor onErrorReturn and the output is just nothing:
0:55:22: Executing ':reactive-programming-using-reactor:FluxAndMonoGeneratorService.main()'...
> Task :reactive-programming-using-reactor:generateLombokConfig UP-TO-DATE
> Task :reactive-programming-using-reactor:compileJava
> Task :reactive-programming-using-reactor:processResources NO-SOURCE
> Task :reactive-programming-using-reactor:classes
> Task :reactive-programming-using-reactor:FluxAndMonoGeneratorService.main()
00:55:23.715 [main] DEBUG reactor.util.Loggers$LoggerFactory - Using Slf4j logging framework
BUILD SUCCESSFUL in 1s
What is the reason for this ? (I mean at least onError I am expecting but nothing...)
note: mergeWith() is also not working with this delayElements()

subscribe is not blocking operation and delayElements will be scheduled on another thread (by default parallel Scheduler). As result your program exits before elements are emitted. Here is a test
#Test
void mergeWithDelayElements() {
Flux<String> abcFlux = Flux.just("A", "B", "C").delayElements(Duration.ofMillis(151));
Flux<String> defFlux = Flux.just("D", "E", "F").delayElements(Duration.ofMillis(100));
StepVerifier.create(Flux.merge(abcFlux, defFlux))
.expectNext("D", "A", "E", "B", "F", "C")
.verifyComplete();
}

Related

IntelliJ check problem during Hyperskill Kotlin learning

I'm working on a Jetbrains Hyperskill track KOTLIN, it's my third project and I never had this kind of problem.
I found this post (here), and tried their suggestions (Which are the same that JetBrains give on their wiki/FAQ), but didn't work.
The project is:
Unit Converter (Heavy Duty Step 4/5)
Here is my code:
package converter
fun main() {
loopcheck# while (true) {
var conversion: Double
print("Enter what you want to convert (or exit): ")
val userInput = readln()
if (userInput == "exit") break#loopcheck
val (originalNumber, originalUnit, convertedUnit) = userInputSplit(userInput)
// Validating inputs/Enums + exception checks
if (originalNumber == null) {
println("Wrong number")
continue#loopcheck
}
if (originalUnit == null && convertedUnit != null) {
println("Conversion from ??? to $convertedUnit is impossible")
continue#loopcheck
}
if (originalUnit != null && convertedUnit == null) {
println("Conversion from $originalUnit to ??? is impossible")
continue#loopcheck
}
if (originalUnit == null && convertedUnit == null) {
println("Conversion from ??? to ??? is impossible")
continue#loopcheck
}
if (originalUnit != null && convertedUnit != null) {
if (originalUnit.type != convertedUnit.type) {
println("Conversion from ${originalUnit.plural} to ${convertedUnit.plural} is impossible")
continue#loopcheck
} else {
// Conversion Calculus
conversion = originalNumber * originalUnit.ratio / convertedUnit.ratio
// Check if the units are singular or plural
val preUnitCheck = if (originalNumber == 1.0) originalUnit.singular else originalUnit.plural
val postUnitCheck = if (conversion == 1.0) convertedUnit.singular else convertedUnit.plural
// Prints final text
println("$originalNumber $preUnitCheck is $conversion $postUnitCheck")
}
}
}
}
// Function to organize userInput in 3 variables: Number Unit1 Unit2
fun userInputSplit(userInput: String): Triple<Double?, Unidade?, Unidade?> {
val userInputArray = userInput.lowercase().split(" ")
val originalNumber = try {
userInputArray[0].toDouble()
} catch (e: NumberFormatException) { null }
val originalUnit = try {
getUnit(userInputArray[1])
} catch (e: IllegalArgumentException) { null }
val convertedUnit = try {
getUnit(userInputArray[2])
} catch (e: IllegalArgumentException) { null }
return Triple(originalNumber, originalUnit, convertedUnit)
}
// Function to set constant from Unidade for conversion based from User Input.
fun getUnit(unit: String): Unidade =
when (unit) {
"m", "meter", "meters" -> Unidade.METER
"km", "kilometer", "kilometers" -> Unidade.KILOMETER
"cm", "centimeter", "centimeters" -> Unidade.CENTIMETER
"mm", "millimeter", "millimeters" -> Unidade.MILLIMETER
"mi", "mile", "miles" -> Unidade.MILE
"yd", "yard", "yards" -> Unidade.YARD
"ft", "foot", "feet" -> Unidade.FOOT
"in", "inch", "inches" -> Unidade.INCH
"g", "gram", "grams" -> Unidade.GRAM
"kg", "kilogram", "kilograms" -> Unidade.KILOGRAM
"mg", "milligram", "milligrams" -> Unidade.MILLIGRAM
"lb", "pound", "pounds" -> Unidade.POUND
"oz", "ounce", "ounces" -> Unidade.OUNCE
// "degree celsius", "degrees celsius", "celsius", "dc", "c" -> Unit.CELSIUS
// "degree fahrenheit", "degrees fahrenheit", "fahrenheit", "df", "f" -> Unit.FAHRENHEIT
// "kelvin", "kelvins", "k" -> Unit.Kelvin
else -> throw IllegalArgumentException ("Wrong Unit. Try Again.")
}
enum class Unidade (val short: String,
val singular: String,
val plural: String,
val ratio: Double,
val type: String
) {
METER("m","meter", "meters", 1.0, "Length"),
KILOMETER("km","kilometer", "kilometers", 1000.0, "Length"),
CENTIMETER("cm","centimeter", "centimeters", 0.01, "Length"),
MILLIMETER("mm", "millimeter", "millimeters", 0.001, "Length"),
MILE("mi","mile", "miles", 1609.35, "Length"),
YARD("yd","yard", "yards", 0.9144, "Length"),
FOOT("ft","foot", "feet", 0.3048, "Length"),
INCH("in","inch", "inches", 0.0254, "Length"),
GRAM("g", "gram", "grams", 1.0, "Weight"),
KILOGRAM("kg", "kilogram", "kilograms", 1000.0, "Weight"),
MILLIGRAM("mg", "milligram", "milligrams", 0.001, "Weight"),
POUND("lb", "pound", "pounds", 453.592, "Weight"),
OUNCE("oz","ounce", "ounces", 28.3495, "Weight");
//CELSIUS("degree Celsius", "degrees Celsius", 1.0, "Temperature"),
//KELVIN("Kelvin", "Kelvins", 1.0, "Temperature"),
//FAHRENHEIT("degree Fahrenheit", "degrees Fahrenheit", 1.0, "Temperature")
}
Every time I try to check my code with Hyperskill, this happens now:
Failed to launch checking
FAILURE: Build failed with an exception.
What went wrong:
Execution failed for task ':Unit_Converter-task:compileTestKotlin'.
Error while evaluating property 'filteredArgumentsMap' of task ':Unit_Converter-task:compileTestKotlin'
Could not resolve all files for configuration ':Unit_Converter-task:testCompileClasspath'.
> Could not find com.github.hyperskill:hs-test:release-SNAPSHOT.
Searched in the following locations:
- https://repo.maven.apache.org/maven2/com/github/hyperskill/hs-test/release-SNAPSHOT/maven-metadata.xml
- https://repo.maven.apache.org/maven2/com/github/hyperskill/hs-test/release-SNAPSHOT/hs-test-release-SNAPSHOT.pom
- https://jitpack.io/com/github/hyperskill/hs-test/release-SNAPSHOT/maven-metadata.xml
- https://jitpack.io/com/github/hyperskill/hs-test/release-SNAPSHOT/hs-test-release-v8-g6845035-132-v8-g6845035-132.pom
Required by:
project :Unit_Converter-task
Try:
Run with --stacktrace option to get the stack trace.
Run with --info or --debug option to get more log output.
Run with --scan to get full insights.
Get more help at https://help.gradle.org
BUILD FAILED in 16s
Task :Unit_Converter-task:compileKotlin
Task :Unit_Converter-task:compileJava NO-SOURCE
Task :Unit_Converter-task:processResources NO-SOURCE
Task :Unit_Converter-task:classes UP-TO-DATE
Task :util:compileKotlin NO-SOURCE
Task :util:compileJava NO-SOURCE
Task :util:processResources NO-SOURCE
Task :util:classes UP-TO-DATE
Task :util:compileTestKotlin NO-SOURCE
Task :util:compileTestJava NO-SOURCE
Task :util:processTestResources NO-SOURCE
Task :util:testClasses UP-TO-DATE
Task :Unit_Converter-task:compileTestKotlin FAILED
2 actionable tasks: 2 executed
Open the build.gradle file in the root directory of your JetBrains Academy project and replace testImplementation 'com.github.hyperskill:hs-test:release-SNAPSHOT' with testImplementation 'com.github.hyperskill:hs-test:master-SNAPSHOT'.
After reaching JETBRAINS support we did some actions. In the end, the problem was solved. Down below the steps taken.
1st try:
Open build.gradle in your project folder and replace
testImplementation 'com.github.hyperskill:hs-test:release-SNAPSHOT'
with testImplementation
'com.github.hyperskill:hs-test:master-SNAPSHOT'
The build output after the modification changed to a different error message.
Compilation Failed e: C:\Users\rafam\IdeaProjects\Unit Converter\Unit
Converter\task\test\Task2Test.kt: (6, 1): Conflicting overloads:
public fun authorsCase(input: String, isPrivate: Boolean = ...):
TestCase defined in root package in file Task2Test.kt,
public fun authorsCase(input: String, isPrivate: Boolean = ...):
TestCase defined in root package in file Task4Test.kt e:
C:\Users\rafam\IdeaProjects\Unit Converter\Unit
Converter\task\test\Task2Test.kt: (6, 81): Unresolved reference:
Authors e: C:\Users\rafam\IdeaProjects\Unit Converter\Unit
Converter\task\test\Task2Test.kt: (6, 90): Unresolved reference: solve
e: C:\Users\rafam\IdeaProjects\Unit Converter\Unit
Converter\task\test\Task2Test.kt: (11, 13): Overload resolution
ambiguity: public fun authorsCase(input: String, isPrivate: Boolean =
...): TestCase defined in root package in file
Task2Test.kt public fun authorsCase(input: String, isPrivate: Boolean
= ...): TestCase defined in root package in file Task4Test.kt ...
FAILURE: Build failed with an exception.
What went wrong: Execution failed for task ':Unit_Converter-task:compileTestKotlin'.
After this error, Jetbrains support suggested new steps:
Please try re-creating the project by following the steps below: Go to
the affected JetBrains Academy project’s directory and move it
somewhere else or make a backup.
On the Welcome Screen of your IDE, go to the My Courses tab. Highlight
the affected project and click ✕. Select Remove Course.
Start a JetBrains Academy project by going to the JetBrains Academy
tab in File | Learn and Teach | Browse Courses.
After that, please ensure that JDK 17 is selected as Gradle JVM in
Settings/Preferences | Build, Execution, Deployment | Build Tools |
Gradle and as Project SDK in File | Project Structure.
I've changed and updated everything as suggested and the build output changed AGAIN:
Failed to launch checking
FAILURE: Build failed with an exception.
What went wrong: Execution failed for task ':Unit_Converter-task:compileTestKotlin'.
Error while evaluating property 'filteredArgumentsMap' of task ':Unit_Converter-task:compileTestKotlin'
Could not resolve all files for configuration ':Unit_Converter-task:testCompileClasspath'.
> Could not find com.github.hyperskill:hs-test:release-SNAPSHOT.
Searched in the following locations:
- https://repo.maven.apache.org/maven2/com/github/hyperskill/hs-test/release-SNAPSHOT/maven-metadata.xml
- https://repo.maven.apache.org/maven2/com/github/hyperskill/hs-test/release-SNAPSHOT/hs-test-release-SNAPSHOT.pom
- https://jitpack.io/com/github/hyperskill/hs-test/release-SNAPSHOT/maven-metadata.xml
- https://jitpack.io/com/github/hyperskill/hs-test/release-SNAPSHOT/hs-test-release-v8-g6845035-132-v8-g6845035-132.pom
Required by:
project :Unit_Converter-task
After sending this output to Jetbrains they requested again to open build.gradle in my project folder and replace testImplementation 'com.github.hyperskill:hs-test:release-SNAPSHOT' with testImplementation 'com.github.hyperskill:hs-test:master-SNAPSHOT'.
This answer took 2-3 days to be replied. After that, the check worked.

NestedClass test failing, because Spring-Data-Mongo-Reactive is closing MongoDb connection (state should be: server session pool is open)

1) Problem Description:
I am using a Spring-Data-Mongo-Reactive, Testcontainers and JUnit 05;
I have a Test-Class with simple-test and ‘Nested-Test-Class’(which has a simple test, as well);
When, JUnit tests the NestedClass, the MongoDb Connection is closed, and the test 'Test's NestedClass' fail;
My Goal is:
Keep the Reactive-MongoDB-Connection opened, in order to test, the ‘Nested-Test-Class’;
Below is the code for the above situation:
1.1) Code:
Current working status: not working;
Current behaviour:
The Reactive-MongoDB connection is closing, when the ‘Nested-Test-Class’ is being tested, even though the first test is tested normally. .
#Import(ServiceCrudRepoCfg.class)
#TestcontainerAnn
#TestsMongoConfigAnn
#TestsGlobalAnn
public class Lab {
final private String enabledTest = "true";
#Autowired
IService serviceCrudRepo;
#Test
#DisplayName("Save")
#EnabledIf(expression = enabledTest, loadContext = true)
public void save() {
Person localPerson = personWithIdAndName().create();
StepVerifier
.create(serviceCrudRepo.save(localPerson))
.expectSubscription()
.expectNext(localPerson)
.verifyComplete();
}
#Nested
#DisplayName("Nested Class")
#Execution(SAME_THREAD)
class NestedClass {
#Test
#DisplayName("findAll")
#EnabledIf(expression = enabledTest, loadContext = true)
public void findAll() {
StepVerifier
.create(serviceCrudRepo.findAll()
.log())
.expectSubscription()
.expectNextCount(1L)
.verifyComplete();
}
}
}
2) Current Problematic Log / Error:
java.lang.AssertionError: expectation "expectNextCount(1)" failed (expected: count = 1; actual: counted = 0; signal: onError(org.springframework.data.mongodb.ClientSessionException: state should be: server session pool is open; nested exception is java.lang.IllegalStateException: state should be: server session pool is open))
Caused by: java.lang.IllegalStateException: state should be: server session pool is open
3) Question:
How Can I Keep the Reactive-MongoDB-Connection opened, in order to test the ‘Nested-Test-Class’ as well?
Thanks a lot for any help

Corda: Party rejected session request as Requestor has not been registered

I've a Corda application that using M14 to build and run corda to run a TwoPartyProtocol where either parties can exchange data to reach a data validity consensus. I've followed Corda flow cookbook to build a flow.
Also, after reading the docs from several different corda milestones I've understood that M14 no longer needs flowSessions as mentioned in the release notes which also eliminates need to register services.
My TwoPartyFlow with inner FlowLogics:
class TwoPartyFlow{
#InitiatingFlow
#StartableByRPC
open class Requestor(val price: Long,
val otherParty: Party) : FlowLogic<SignedTransaction>(){
#Suspendable
override fun call(): SignedTransaction {
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
send(otherParty, price)
/*Some code to generate SignedTransaction*/
}
}
#InitiatedBy(Requestor::class)
open class Responder(val requestingParty : Party) : FlowLogic<SignedTransaction>(){
#Suspendable
override fun call(): SignedTransaction {
val request = receive<Long>(requestor).unwrap { price -> price }
println(request)
/*Some code to generate SignedTransaction*/
}
}
}
But, running the above using startTrackedFlow from Api causes the above error:
Party CN=Other,O=Other,L=NY,C=US rejected session request: com.testapp.flow.TwoPartyFlow$Requestor has not been registered
I had hard time finding the reason from corda docs or logs since Two Party flow implementations have changed among several Milestones of corda. Can someone help me understand the problem here.
My API Call:
#GET
#Path("start-flow")
fun requestOffering(#QueryParam(value = "price") price: String) : Response{
val price : Long = 10L
/*Code to get otherParty details*/
val otherPartyHostAndPort = HostAndPort.fromString("localhost:10031")
val client = CordaRPCClient(otherPartyHostAndPort)
val services : CordaRPCOps = client.start("user1","test").proxy
val otherParty: Party = services.nodeIdentity().legalIdentity
val (status, message) = try {
val flowHandle = services.startTrackedFlow(::Requestor, price, otherParty)
val result = flowHandle.use { it.returnValue.getOrThrow() }
// Return the response.
Response.Status.CREATED to "Transaction id ${result.id} committed to ledger.\n"
} catch (e: Exception) {
Response.Status.BAD_REQUEST to e.message
}
return Response.status(status).entity(message).build()
}
My Gradle deployNodes task:
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['build']) {
directory "./build/nodes"
networkMap "CN=Controller,O=R3,OU=corda,L=London,C=UK"
node {
name "CN=Controller,O=R3,OU=corda,L=London,C=UK"
advertisedServices = ["corda.notary.validating"]
p2pPort 10021
rpcPort 10022
cordapps = []
}
node {
name "CN=Subject,O=Subject,L=NY,C=US"
advertisedServices = []
p2pPort 10027
rpcPort 10028
webPort 10029
cordapps = []
rpcUsers = [[ user: "user1", "password": "test", "permissions": []]]
}
node {
name "CN=Other,O=Other,L=NY,C=US"
advertisedServices = []
p2pPort 10030
rpcPort 10031
webPort 10032
cordapps = []
rpcUsers = [[ user: "user1", "password": "test", "permissions": []]]
}
There appears to be a couple of problems with the code you posted:
The annotation should be #StartableByRPC, not #StartableNByRPC
The price passed to startTrackedFlow should be a long, not an int
However, even after fixing these issues, I couldn't replicate your error. Can you apply these fixes, do a clean re-deploy of your nodes (gradlew clean deployNodes), and see whether the error changes?
You shouldn't be connecting to the other node via RPC. RPC is how a node's owner speaks to their node. In the real world, you wouldn't have the other node's RPC credentials, and couldn't log into the node in this way.
Instead, you should use your own node's RPC client to retrieve the counterparty's identity:
val otherParty = services.partyFromX500Name("CN=Other,O=Other,L=NY,C=US")!!
See an M14 example here: https://github.com/corda/cordapp-example/blob/release-M14/kotlin-source/src/main/kotlin/com/example/api/ExampleApi.kt.

How do I show a list of all the test failures after completion of a gradle task involving tests

After running gradle tasks that include tests on my multi-module project, I want to see a summary of every test failure across all modules, e.g.
module 1:
testmodule1thing1 PASSED
testmodule1thing2 FAILED
results
2 tests 1 passed 1 failed
module 2:
testmodule2thing1 PASSED
testmodule2thing2 FAILED
results
2 tests 1 passed 1 failed
module 3:
testmodule3thing1 FAILED
results
1 tests 1 passed 1 failed
BUILD FAILED
========= I already have everything above this line
test failures:
testmodule1thing1
testmodule2thing2
testmodule3thing1
========= I want everything between the last line and this line
Is this possible? If so, how? If a full task summary isn't possible, I can live with a per-module summary
This can also be accomplished directly within the test task itself:
tasks.withType(Test) {
// a collection to track failedTests
ext.failedTests = []
afterTest { descriptor, result ->
if (result.resultType == TestResult.ResultType.FAILURE) {
String failedTest = "${descriptor.className}::${descriptor.name}"
logger.debug("Adding " + failedTest + " to failedTests...")
failedTests << [failedTest]
}
}
afterSuite { suite, result ->
if (!suite.parent) { // will match the outermost suite
// logs each failed test
if (!failedTests.empty) {
logger.lifecycle("Failed tests:")
failedTests.each { failedTest ->
logger.lifecycle("${failedTest}")
}
}
}
}
}
You can use a testlistener in combination with the buildFinished hook for that. A very simple solution can look like this first draft:
allprojects {
// add a collection to track failedTests
ext.failedTests = []
// add a testlistener to all tasks of type Test
tasks.withType(Test) {
afterTest { TestDescriptor descriptor, TestResult result ->
if(result.resultType == org.gradle.api.tasks.testing.TestResult.ResultType.FAILURE){
failedTests << ["${descriptor.className}::${descriptor.name}"]
}
}
}
// print out tracked failed tests when the build has finished
gradle.buildFinished {
if(!failedTests.empty){
println "Failed tests for ${project.name}:"
failedTests.each { failedTest ->
println failedTest
}
println ""
}
}
}
Another option to have better visibility for your failed tests is maybe using gradle build scans (https://plugins.gradle.org/plugin/com.gradle.build-scan).

RxJava timeout without emiting error?

Is there an option to have variant of timeout that does not emit Throwable?
I would like to have complete event emited.
You don't need to map errors with onErrorResumeNext. You can just provide a backup observable using:
timeout(long,TimeUnit,Observable)
It would be something like:
.timeout(500, TimeUnit.MILLISECONDS, Observable.empty())
You can resume from an error with another Observable, for example :
Observable<String> data = ...
data.timeout(1, TimeUnit.SECONDS)
.onErrorResumeNext(Observable.empty())
.subscribe(...);
A simpler solution that does not use Observable.timeout (thus it does not generate an error with the risk of catching unwanted exceptions) might be to simply take until a timer completes:
Observable<String> data = ...
data.takeUntil(Observable.timer(1, TimeUnit.SECOND))
.subscribe(...);
You can always use onErrorResumeNext which will get the error and you can emit whatever item you want-
/**
* Here we can see how onErrorResumeNext works and emit an item in case that an error occur in the pipeline and an exception is propagated
*/
#Test
public void observableOnErrorResumeNext() {
Subscription subscription = Observable.just(null)
.map(Object::toString)
.doOnError(failure -> System.out.println("Error:" + failure.getCause()))
.retryWhen(errors -> errors.doOnNext(o -> count++)
.flatMap(t -> count > 3 ? Observable.error(t) : Observable.just(null)),
Schedulers.newThread())
.onErrorResumeNext(t -> {
System.out.println("Error after all retries:" + t.getCause());
return Observable.just("I save the world for extinction!");
})
.subscribe(s -> System.out.println(s));
new TestSubscriber((Observer) subscription).awaitTerminalEvent(500, TimeUnit.MILLISECONDS);
}