Closed raph1mm closed 4 years ago
Hi raph1mm,
I will have a look but you can try setting quickfixj.client.jmx-enabled=false
if you don't need the MBean for your tests.
Could you share your project in GitHub so I can have a look?
I will have a look but you can try setting
quickfixj.client.jmx-enabled=false
if you don't need the MBean for your tests.
I'm quite new to Java world, but I believe I need it - one of integration test I have is requesting my application using Rest Assured. I need complete application for this.
I've found not ideal solution. I can prevent reloading application context between test classes if all test classes have the same parent class, for example:
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public abstract class BaseTestApplication {
}
Could you share your project in GitHub so I can have a look?
I can't - because of NDA. :(
Maybe I can provide more information for you? What do you want to know?
I wanted to see the test classes and the spring boot test config. I will try to reproduce this issue
Ok. I'm preparing some code for you.
Ok. This code is not pretty, but it's only proof of concept for you:
I created this controller:
@RestController
public class MyController {
@GetMapping(path = "/path1")
public ResponseEntity<?> getPath1() throws SessionNotFound {
QuoteRequest quoteRequest = createQuoteRequest(UUID.randomUUID());
SessionID sessionID = new SessionID("FIX.4.2", "XXX-XXXX-TEST", "XXX-XXXX-TEST");
Session.sendToTarget(quoteRequest, sessionID);
return ResponseEntity.ok("OK");
}
@GetMapping(path = "/path2")
public ResponseEntity<?> getPath2() throws SessionNotFound {
QuoteRequest quoteRequest = createQuoteRequest(UUID.randomUUID());
SessionID sessionID = new SessionID("FIX.4.2", "XXX-XXX-TEST", "XXX-XXXX-TEST");
Session.sendToTarget(quoteRequest, sessionID);
return ResponseEntity.ok("OK");
}
private QuoteRequest createQuoteRequest(
UUID operationId) {
QuoteRequest quoteRequest = new QuoteRequest(new QuoteReqID(operationId.toString()));
return quoteRequest;
}
}
and some tests (tests have no addiotional setup - only via annotations):
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class MyController1IntegrationTest {
@Test
public void canGetPath1() {
given()
.contentType("application/json")
.when()
.get("/myapp/path1")
.then()
.assertThat()
.statusCode(200);
}
}
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class MyController2IntegrationTest {
@Test
public void canGetPath2() {
given()
.contentType("application/json")
.when()
.get("/myapp/path2")
.then()
.assertThat()
.statusCode(200);
}
}
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class QuoteRepositoryTest {
@Autowired
private QuoteRepository repository;
@Test
public void someRepoStuff() {
repository.findByQuoteId("123");
}
}
I had to use @DirtiesContext in the last one to enforce situation with application reloading (in my orginal code it reloads context without it).
When I run:
mvn clean test
InstanceAlreadyExistsException happen.
To make sure that happen, you should see
at least twice.
Hi @raph1mm
I just added a branch with your code and tests and everything worked fine (https://github.com/esanchezros/quickfixj-spring-boot-starter-examples/tree/add-spring-integration-test - See simple-server-sender
)
Just a thought, could you check if you have another instance of the app running elsewhere? It could be that you already have a server running and that, having quickfixj.server.jmx-enabled=true
, will cause the issue described.
Hi @esanchezros
Thank you for checking. :)
I ran your'e example. Please add
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
before every test class. Then you can see Spring Boot logo twice during tests - but even then - your example works fine.
I noticed that your setup is different. For example - I cannot see "ThreadedSocketInitiator" bean. Maybe here is something wrong?
Hi @raph1mm
I changed the tests (pushed it to examples) and added the @DirtiesContext
on every class, plus added the config as in the original post, still everything built fine.
Before running any tests, could you run jconsole
from the command line and see if there is already a local process running?
Thanks
Hi,
I only see this:
Hi @raph1mm,
I'm still curious to see why you were getting this error. Did you get to the bottom of it?
Thanks
Hi @raph1mm
tl;dr
I managed to reproduced your issue and found the root cause.
Full explanation
The spring starter register two beans, serverAcceptorMBean
and clientInitiatorMBean
, that create a JmxExporter
. The object needs REGISTRATION_REPLACE_EXISTING
set in registration behaviour to override the existing MBean
. This comment is in theJmxExporter
javadoc:
* Actually register the MBean with the server. The behaviour when encountering
* an existing MBean can be configured using the registrationBehaviour constructor or {@link #setRegistrationBehavior(int)}.
* This design (and also code) was unashamedly cribbed from Spring's
* <a href="http://static.springframework.org/spring/docs/2.0.x/api/org/springframework/jmx/support/MBeanRegistrationSupport.html">MBeanRegistrationSupport</a>
* class. Thanks Spring team!
*
* @see #REGISTRATION_FAIL_ON_EXISTING
* @see #REGISTRATION_IGNORE_EXISTING
* @see #REGISTRATION_REPLACE_EXISTING
The default behaviour is set to REGISTRATION_FAIL_ON_EXISTING
, hence when reloading the Spring context the MBean
registration fails.
A workaround for this issue is to set quickfixj.server.jmx-enabled=false
which will prevent the bean from registering the `MBean.
I will fix this and release a new version shortly.
Hi @esanchezros
I wanted to reply that I haven't found other solution than common parent class for all tests.
I'll try your workaround. :)
This setup works for me:
quickfixj:
client:
config: ${QUIICKFIXJ_CLIENT_CONFIG_FILE:classpath:barxfx.cfg}
jmx-enabled: false
server:
jmx-enabled: false
Anyway - thank you very much for your time and helping me with this. :)
Hi @raph1mm
I've release version 2.5.2
with a fix for this issue. Could you update your version and try with @DirtiesContext
on separate classes?
Thanks
I've just tested it. It works just fine. :)
Thank you, again.
Hello,
I'm having some issues during integration tests in Spring Boot.
I have app which uses Quickfix Client, here's my main class:
I've got some integrations tests and during the second one (and next) I got this exception:
You can see "Caused by: javax.management.InstanceAlreadyExistsException" - it looks like the previous test didn't destroy bean related to Quickfix. What's the issue here?
I tried using "@DirtyContext" in tests but with no luck.