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

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

Related

Gatling feeder/parameter issue - Exception in thread "main" java.lang.UnsupportedOperationException

I just involved the new project for API test for our service by using Gatling. At this point, I want to search query, below is the code:
def chnSendToRender(testData: FeederBuilderBase[String]): ChainBuilder = {
feed(testData)
exec(api.AdvanceSearch.searchAsset(s"{\"all\":[{\"all:aggregate:text\":{\"contains\":\"#{edlAssetId}_Rendered\"}}]}", "#{authToken}")
.check(status.is(200).saveAs("searchStatus"))
.check(jsonPath("$..asset:id").findAll.optional.saveAs("renderedAssetList"))
)
.doIf(session => session("searchStatus").as[Int] == 200) {
exec { session =>
printConsoleLog("Rendered Asset ID List: " + session("renderedAssetList").as[String], "INFO")
session
}
}
}
I declared the feeder already in the simulation scala file:
class GVRERenderEditor_new extends Simulation {
private val edlToRender = csv("data/render/edl_asset_ids.csv").queue
private val chnPostRender = components.notifications.notice.JobsPolling_new.chnSendToRender(edlToRender)
private val scnSendEDLForRender = scenario("Search Post Render")
.exitBlockOnFail(exec(preSimAuth))
.exec(chnPostRender)
setUp(
scnSendEDLForRender.inject(atOnceUsers(1)).protocols(httpProtocol)
)
.maxDuration(sessionDuration.seconds)
.assertions(global.successfulRequests.percent.is(100))
}
But Gatling test failed to run, showing this error: Exception in thread "main" java.lang.UnsupportedOperationException: There were no requests sent during the simulation, reports won't be generated
If I hardcode the #{edlAssetId} (put the real edlAssetId in that query), I will get result. I think I passed the parameter wrongly in this case. I've tried to print the output in console log but no luck. What's wrong with this code? I would appreciate your help. Thanks!
feed(testData)
exec(api.AdvanceSearch.searchAsset(s"{\"all\":[{\"all:aggregate:text\":{\"contains\":\"#{edlAssetId}_Rendered\"}}]}", "#{authToken}")
.check(status.is(200).saveAs("searchStatus"))
.check(jsonPath("$..asset:id").findAll.optional.saveAs("renderedAssetList"))
)
You're missing a . (dot) before the exec to attach it to the feed.
As a result, your method is returning the last instruction, ie the exec only.

Only on Windows: "Socket fail to connect address already in use" (Exposed, Koin, Flowables)

I only encounter this problem when I am on Windows and actively work on the project with IntelliJ Idea.
When I deploy it onto the Linux machine everything works fine.
I already updated exposed, but it didn't help.
The errors come in very quick succession and make using the app impossible.
Additional libraries I use: Flyway, RxJava, Koin, Exposed
Edit: To clarify, it works for a time, but at some point it always starts with the errors and then doesn't stop.
In the Application.kt
installKoin(
listOf(
postgresModule(postgresConfig),
mariaDBModule(mariaDBConfig),
)
)
TransactionManager.defaultDatabase = get("mariaDB")
Database connection:
fun mariaDBModule(databaseConfig: DatabaseConfig): Module {
val database = Database.connect(
url = databaseConfig.url,
driver = databaseConfig.driver,
user = databaseConfig.user,
password = databaseConfig.password
)
return module {
TransactionManager.defaultDatabase = database
single(name ="mariaDB") { database }
}
}
fun postgresModule(postgresConfig: PostgresConfig): Module {
val database = Database.connect(
url = postgresConfig.url,
driver = postgresConfig.driver,
user = postgresConfig.user,
password = postgresConfig.password
)
return module {
single(name = "postgres") {database}
}
}
Edit:
I also use a second external postgres Database and the Error only starts (I think, hard to say) coming when I use a function that queries the postgres Database. I added it above.
Where it is used with a Flowable:
private fun observeDevices() {
m2mClient.subscribe("devices/#")
.doOnNext { message ->
m2MRepository.persistMessage(message) //Error Here
changeState.onNext(message)
triggerOnMessage(message)
}
.ignoreElements()
.retry()
.subscribe()
}
Persist function:
fun persistMessage(message: M2MMessage) = transaction(mariaDB) {
M2MMessagesTable.replace {
it[M2MMessagesTable.broker] = message.broker
it[M2MMessagesTable.topic] = message.topic
it[M2MMessagesTable.message] = message.message
it[M2MMessagesTable.retained] = message.retained
it[M2MMessagesTable.timestamp] = message.timestamp
it[M2MMessagesTable.received] = message.received
}
}
Exception:
2022-06-28 17:23:37.044 [RxComputationThreadPool-3] WARN Exposed - Transaction attempt #2 failed: java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=localhost)(port=3306)(type=master) : Socket fail to connect to host:localhost, port:3306. Address already in use: connect. Statement(s): REPLACE INTO m2m_message (broker, message, received, retained, `timestamp`, topic) VALUES (?, ?, ?, ?, ?, ?)
org.jetbrains.exposed.exceptions.ExposedSQLException: java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=localhost)(port=3306)(type=master) : Socket fail to connect to host:localhost, port:3306. Address already in use: connect
at org.jetbrains.exposed.sql.statements.Statement.executeIn$exposed_core(Statement.kt:49)
at org.jetbrains.exposed.sql.Transaction.exec(Transaction.kt:138)
at org.jetbrains.exposed.sql.Transaction.exec(Transaction.kt:124)
at org.jetbrains.exposed.sql.statements.Statement.execute(Statement.kt:28)
at org.jetbrains.exposed.sql.QueriesKt.replace(Queries.kt:202)
at de.<redacted>.server.m2m.M2MRepository$persistMessage$1.invoke(M2MRepository.kt:55)
at de.<redacted>.server.m2m.M2MRepository$persistMessage$1.invoke(M2MRepository.kt:54)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.inTopLevelTransaction$run(ThreadLocalTransactionManager.kt:189)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.access$inTopLevelTransaction$run(ThreadLocalTransactionManager.kt:1)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt$inTopLevelTransaction$1.invoke(ThreadLocalTransactionManager.kt:215)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.keepAndRestoreTransactionRefAfterRun(ThreadLocalTransactionManager.kt:223)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.inTopLevelTransaction(ThreadLocalTransactionManager.kt:214)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt$transaction$1.invoke(ThreadLocalTransactionManager.kt:165)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.keepAndRestoreTransactionRefAfterRun(ThreadLocalTransactionManager.kt:223)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.transaction(ThreadLocalTransactionManager.kt:135)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.transaction(ThreadLocalTransactionManager.kt:132)
at de.<redacted>.server.m2m.M2MRepository.persistMessage(M2MRepository.kt:54)
at de.<redacted>.server.device.m2m.DeviceM2MService.observeDevices$lambda-0(DeviceM2MService.kt:48)
at io.reactivex.internal.operators.flowable.FlowableDoOnEach$DoOnEachSubscriber.onNext(FlowableDoOnEach.java:86)
at io.reactivex.internal.operators.flowable.FlowableMap$MapSubscriber.onNext(FlowableMap.java:68)
at io.reactivex.internal.operators.flowable.FlowableFilter$FilterSubscriber.tryOnNext(FlowableFilter.java:74)
at io.reactivex.internal.operators.flowable.FlowableFilter$FilterConditionalSubscriber.tryOnNext(FlowableFilter.java:139)
at io.reactivex.internal.operators.flowable.FlowableFilter$FilterConditionalSubscriber.onNext(FlowableFilter.java:117)
at io.reactivex.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.tryEmit(FlowableFlatMap.java:282)
at io.reactivex.internal.operators.flowable.FlowableFlatMap$InnerSubscriber.onNext(FlowableFlatMap.java:668)
at io.reactivex.internal.operators.flowable.FlowableMap$MapSubscriber.onNext(FlowableMap.java:68)
at io.reactivex.internal.operators.flowable.FlowableDoOnEach$DoOnEachSubscriber.onNext(FlowableDoOnEach.java:92)
at io.reactivex.internal.operators.flowable.FlowableDoOnLifecycle$SubscriptionLambdaSubscriber.onNext(FlowableDoOnLifecycle.java:79)
at com.hivemq.client.internal.rx.operators.FlowableWithSingleMap$MapSubscriber.onNext(FlowableWithSingleMap.java:130)
at com.hivemq.client.internal.rx.operators.FlowableWithSingleCombine$SplitSubscriber$Default.tryOnNextActual(FlowableWithSingleCombine.java:235)
at com.hivemq.client.internal.rx.operators.FlowableWithSingleCombine$SplitSubscriber.tryOnNext(FlowableWithSingleCombine.java:200)
at io.reactivex.internal.operators.flowable.FlowableObserveOn$ObserveOnConditionalSubscriber.runAsync(FlowableObserveOn.java:649)
at io.reactivex.internal.operators.flowable.FlowableObserveOn$BaseObserveOnSubscriber.run(FlowableObserveOn.java:176)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=localhost)(port=3306)(type=master) : Socket fail to connect to host:localhost, port:3306. Address already in use: connect
at org.mariadb.jdbc.internal.util.exceptions.ExceptionFactory.createException(ExceptionFactory.java:73)
at org.mariadb.jdbc.internal.util.exceptions.ExceptionFactory.create(ExceptionFactory.java:197)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1394)
at org.mariadb.jdbc.internal.util.Utils.retrieveProxy(Utils.java:635)
at org.mariadb.jdbc.MariaDbConnection.newConnection(MariaDbConnection.java:150)
at org.mariadb.jdbc.Driver.connect(Driver.java:89)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:228)
at org.jetbrains.exposed.sql.Database$Companion$connect$10.invoke(Database.kt:206)
at org.jetbrains.exposed.sql.Database$Companion$connect$10.invoke(Database.kt:206)
at org.jetbrains.exposed.sql.Database$Companion$doConnect$3.invoke(Database.kt:127)
at org.jetbrains.exposed.sql.Database$Companion$doConnect$3.invoke(Database.kt:128)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManager$ThreadLocalTransaction$connectionLazy$1.invoke(ThreadLocalTransactionManager.kt:69)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManager$ThreadLocalTransaction$connectionLazy$1.invoke(ThreadLocalTransactionManager.kt:68)
at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManager$ThreadLocalTransaction.getConnection(ThreadLocalTransactionManager.kt:75)
at org.jetbrains.exposed.sql.Transaction.getConnection(Transaction.kt)
at org.jetbrains.exposed.sql.statements.InsertStatement.prepared(InsertStatement.kt:157)
at org.jetbrains.exposed.sql.statements.Statement.executeIn$exposed_core(Statement.kt:47)
... 39 common frames omitted
Caused by: java.sql.SQLNonTransientConnectionException: Socket fail to connect to host:localhost, port:3306. Address already in use: connect
at org.mariadb.jdbc.internal.util.exceptions.ExceptionFactory.createException(ExceptionFactory.java:73)
at org.mariadb.jdbc.internal.util.exceptions.ExceptionFactory.create(ExceptionFactory.java:188)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.createSocket(AbstractConnectProtocol.java:257)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.createConnection(AbstractConnectProtocol.java:524)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1389)
... 55 common frames omitted
Caused by: java.net.BindException: Address already in use: connect
at java.base/java.net.PlainSocketImpl.waitForConnect(Native Method)
at java.base/java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:107)
at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412)
at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255)
at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.base/java.net.Socket.connect(Socket.java:609)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.createSocket(AbstractConnectProtocol.java:252)
... 57 common frames omitted
2022-06-28 17:23:37.044 [RxComputationThreadPool-3] DEBUG MqttClientV5 - subscribing to devices/#

ConcurrentDictionary apparently not working in ASP.NET controller

Why is the concurrent dictionary not behaving like a concurrent dictionary?
[Route("aaa")]
[HttpPost]
public Outbound Post(Inbound inbound)
{
Outbound outbound = new Outbound();
TaskState taskState = new TaskState();
taskState.state = 0;
TaskState s;
bool rc = taskDictionary.TryGetValue(inbound.taskId, out s);
if (rc == false)
taskDictionary.GetOrAdd(inbound.taskId, taskState);
else
return null;
if (s != null)
return null;
rc = taskDictionary.TryGetValue(inbound.taskId, out s);
if (rc)
{
string m0 = String.Format("POST dictionary count is " + taskDictionary.Count);
_logger.Log(LogLevel.Error, m0);
}
else
return null;
_logger.Log(LogLevel.Error, "POST method is doing long running work.");
long Billion = 1000000000;
// work quantity 5 means about 26 seconds // 30 billion is 215 seconds
for (long i = 0; i < inbound.WorkQuantity * Billion; i++)
;
outbound.Message = "The server did some work.";
outbound.BigObject = Modify(inbound.BigObject);
_logger.Log(LogLevel.Error, "POST finished long running work and will soon remove from the dictionary.");
rc = taskDictionary.Remove(inbound.taskId, out s);
if (rc == false)
return null;
if (s == null)
return null;
_logger.Log(LogLevel.Error, "POST is returning the object.");
return outbound;
}
[Route("bbb")]
[HttpPost]
public TaskState PostState(TaskId taskId)
{
TaskState s;
if (taskDictionary.TryGetValue(taskId, out s))
{
_logger.Log(LogLevel.Error, "POSTSTATE, state is " + s.AsString());
return s;
}
else
{
_logger.Log(LogLevel.Error, "POSTSTATE, state not found, dictionary count is " + taskDictionary.Count);
return null;
}
}
TaskDictionary taskDictionary = new TaskDictionary();
class TaskDictionary : ConcurrentDictionary<TaskId, TaskState>
{
internal bool IncrementState(TaskId taskId)
{
TaskState s;
if (TryGetValue(taskId, out s))
{
s.Increment();
return true;
}
else
return false;
}
}
The logging output is...
12.207 +00:00 [Error] MyController: POST dictionary count is 1
12.322 +00:00 [Error] MyController: POST method is doing long running work.
14.361 +00:00 [Error] MyController: POSTSTATE, state not found, dictionary count is 0
40.452 +00:00 [Error] MyController: POST finished long running work and will soon remove from the dictionary.
40.569 +00:00 [Error] MyController: POST is returning the object.
Specifically the problem is that request for the state information does not work because the dictionary appears empty.
So, based on the logging output you are doing two post requests to generate the output that you show us.
The way you initialize the Concurrent Dictionary, is the reason why it returns null on the second request. And that has to do with how the app receives those requests. Each request to your app is independent of another request.
Simply put;
A user POST's to you app.
The requests goes through the middleware pipeline, and eventually it will end up at your controller. Now, here's the important part, the controller will be 'constructed' for this particular request. And it will live for the duration of the request. That's because the lifetime of a controller is scoped by default. So the next request, will construct a new controller and that means that the Dictionary is different from the first one.
So to overcome this scoped request problem, you create a service that contains the dictionary, register this as a singleton (meaning it will only be constructed once and then it's shared), and use dependency injection to use it in the controller.

Why I receive an error when I use exposed in Kotlin?

I need to receive region_name by region_code from Oracle DB
I use Exposed for my program, but I receive error
in thread "main" java.lang.AbstractMethodError
at org.jetbrains.exposed.sql.Transaction.closeExecutedStatements(Transaction.kt:181)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.inTopLevelTransaction(ThreadLocalTransactionManager.kt:137)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.transaction(ThreadLocalTransactionManager.kt:75)
Code is
object Codes : Table("REGIONS") {
val region_code = varchar("region_code",32)
val region_name = varchar("region_name",32)}
The main fun contains
.......
val conn = Database.connect("jdbc:oracle:thin:#//...", driver = "oracle.jdbc.OracleDriver",
user = "...", password = "...")
transaction(java.sql.Connection.TRANSACTION_READ_COMMITTED, 1, conn) {
addLogger(StdOutSqlLogger)
Codes.select { Codes.region_code eq "a" }.limit(1).forEach {
print(it[Codes.region_name])
}
}
AbstractMethodError usually means that you compiled the code with one version of a library, but are running it against a different (incompatible) version.  (See for example these questions.)
So I'd check your dependencies &c carefully.

how to delete a null queue(i.e without queue name ) in activemq 5.8.0?

How to delete a null queue(i.e without queue name ) in activemq 5.8.0 ?
I have a problem with null queue when I delete the null queue with the help of delete button in active 5.8.0 console then throws some Error as shown below.
i.e Error!
Exception occurred while processing this request, check the log for
more information!
What do you want to do next?
There were some issues around creation of Queues with blank names in earlier releases. I'm not sure that you will be successful in deleting the Queue without simply deleting all that KahaDB files and starting over.
One thing to try would be to use JConsole to connect to the broker and invoking the remove operation on the Queue MBean.
we ran into this issue recently and I logged this ticket on it: https://issues.apache.org/jira/browse/AMQ-5211
we are using mkahadb (configured to use a separate directory per destination) and were able to simply delete the corresponding directory (/data//kaha/queue#3a#2f#2f) and restart AMQ...
otherwise, try JMX or you'll need to wipe out the entire message store and start over as Tim suggested...
Here's some code I wrote a while back to deal with a similar problem. It connects using JMX and removes any empty queues that have never been used.
import javax.management.JMX;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.apache.activemq.broker.jmx.BrokerViewMBean;
import org.apache.activemq.broker.jmx.QueueViewMBean;
public class CleanQueues {
public static void main(String[] args) throws Exception {
if (args.length != 1 && args.length != 2) {
System.out.println("Usage: CleanQueues host [port]");
System.exit(1);
}
String host = args[0];
String port = "1099";
if (args.length == 2) {
port = args[2];
}
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://"+host+":"+port+"/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
MBeanServerConnection connection = jmxc.getMBeanServerConnection();
ObjectName broker = null;
for (ObjectName objectName : connection.queryNames(new ObjectName("org.apache.activemq:BrokerName=*,Type=Broker"),null)) {
broker = objectName;
}
if (broker == null) {
System.out.println("Could not find broker name.");
System.exit(2);
}
BrokerViewMBean proxy = JMX.newMBeanProxy(connection, broker, BrokerViewMBean.class);
for (ObjectName n : proxy.getQueues()) {
QueueViewMBean q = JMX.newMBeanProxy(connection, n, QueueViewMBean.class);
if (q.getDispatchCount() == 0 && q.getConsumerCount() == 0) {
System.out.println("Removing queue: "+q.getName());
proxy.removeQueue(q.getName());
}
}
}
}