Application context getting initialized twice - spring

I'm new to Spring and have inherited some Groovy code that relies heavily on Spring. I'm now trying to figure out why my application context is getting intialized twice, and causing multiple copies of my beans to be created.
I've added a #Scheduled task that gets executed with a ThreadPoolTaskExecutor, and inside the task I'm using the application context's getBean static method. In the main program, I'm also using the context to get beans, and I'm finding that the context is getting initialized in both the main program and the scheduled task, which means the task is using a different copy of the bean than the rest of the program.

Ugh, never mind. I was creating two different ApplicationContext objects, both loading the same Config. So problem solved.

Related

DataSource per test with Cucumber and SpringBoot

I have a cucumber test setup with spring boot. There are a large number of integration tests which take a while to run. Because they share a database, the new threaded mode in cucumber 4+ does not work (as expected).
Ideally this would work in Junit also.
For each test, I would like to create a dynamic datasource with a new database/datasource instance that the test can use independently of others, allowing it to run multithreaded (and use the 12 cores I have available).
I have tried #Scope("cucumber-glue") and #Scope("prototype") on the DataSource bean, but this results in org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'dataSource': Requested bean is currently in creation: Is there an unresolvable circular reference?.
If I use the prototype scope, the bean creation method gets called each time, but gives this error, as does the glue scope.
I have also added #DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) to classes and methods, without the scope, but this seems to do nothing.
Is there a way I can either:
1. create a new datasource for each test and have hibernate create the tables?
2. pool a set of datasources that could be used by tests?
3. Populate/reinitialize the context accordingly?
A side consequence of this is that I don't believe my context is getting recreated properly between tests for other instances of the scoping.
#Configuration
public class H2DynamicDataSource {
#Autowired
private Environment env;
#Bean
#Scope("prototype")
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
}
Cheers
R
Hopefully you've solved this.
I just went through something similar and felt like cruising around SlackOverflow to see if anyone was doing something similar (or perhaps asking about how to do something like this) and saw this post. Figured this would be a good place to drop this information in case anyone else tries to go down this road.
I think your asking two questions:
How to get multithreading working with Cucumber and Junit Cucumber?
multithreading works great but you are constrained to a single lane
of test execution by junit if your using either the Cucumber or
SpringJUnit4ClassRunner runner junit runner classes. (I suspect this is why #CucumberOptions doesnt contain a thread arg. It's useless with the current Cucumber runner implementation.)
In order to get this working I had to write my own test runner that
would defer a the entire test execution to Cucumbers Runtime
object. I used a custom cucumber plugin to cache the results and
then relay those results back to junit when asked to 'run' the
individual tests. With Cucumber behind the wheel I was able to allow
any arbitrary number of threads for my tests.
How to ensure a new spring datasource for each test?
If you're unfamiliar with how Spring cache's contexts for tests you should have a look through the documentation here https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testcontext-ctx-management-caching but the tl;dr: Spring's TestContextManager(this is whats under the hood of Springs junit runner) will create and store a spring context in a map keyed by your test configuration. DirtiesContext will force the context to reload.. but otherwise two tests with the same parent class are effectively guaranteed to execute in the same test context. If your datasource is a spring datasource that is initialized during boot.. you definitely need to refresh this context between tests.
Putting those two concepts together.. Cucumber-Spring provides a way to create a new context (consistent with cucumbers new 'world' per test design) for every test but it does so by disregarding any existing spring contexts or data contained therein. This may actually be helpful to you if you can trust Cucumber-Spring to correctly stand up your datasource for you.. but in my situation we had a bunch of issues using this fake context and really needed to pull objects from the default spring context. In my case I had to incorporate Springs TestContextManager into my custom plugin AND write my own Cucumber BackendSupplierimplementation to hijack Cucumbers dependency injection mechanism (effectively replacing Cucumber-Spring)
All in all, what your trying to do is a major PITA and I hope the Cucumber folks make this easier at some point.. but what your trying to do is definitely possible. Hope you got it working!

Bean scope is generating java.lang.UnsatisfiedLinkError

I have multi module maven project,which has one common module which is being used by other modules. In common module I have few beans(Beans are having singleton scope) that are used by other modules application context. Now the problem is having after using those beans in one module(m1) which was not previously using these beans. Importing the common.xml(Beans are defined here) in Application context of module(m1) generates lot of issue(Cannot find the beans). So I decided to directly use those beans in application context of module(m1). If I keep the scope of beans to singelton , I get java.lang.UnsatisfiedLinkError: no jzmq in java.library.path. This issue is solved by using prototype as scope.
Any idea about this issue.
1 Using native methods make your Java application code platform dependent.
2 The System.loadLibrary method is equivalent as executing the Runtime.getRuntime().loadLibrary method.
3 The System.loadLibrary method shall be used in a static initializer block, in order to be loaded only once, when the JVM loads the class for the first time.

Spring Cloud Task Integration Testing

I’m looking for some guidance on the best way of writing integration (ie tests for entire Spring Boot Application) for Spring Cloud Task.
Based on existing documentation and samples I see two approaches for this:
1) Use the standard #SpringBootTest with #TestPropertySource(properties = {"spring.cloud.task.closecontext_enable=false"}
as described here
http://docs.spring.io/spring-cloud-task/docs/1.2.0.M2/reference/htmlsingle/#_writing_your_test
This seems to allow effectively only one test per test class as the task is run when the spring context is initialized ie once per test class. However
#Autowiring of beans in the context into the test class should work to eg to check the results of the task, or examine the state of the task repository.
2) Use SpringApplication.run(MyTaskApplication.class, myArguments); in each test method as in the example here
https://github.com/spring-cloud/spring-cloud-task/blob/master/spring-cloud-task-samples/batch-job/src/test/java/io/spring/BatchJobApplicationTests.java
This allows me to write multiple tests in the test class each with potentially different spring properties or batch job parameters.
The main problem I have with either approach that I can’t see how to get access eg #Autowire to beans in the context such as JdbcTemplate (eg to insert test input data for a job into an embedded db) or RestTemplate (to set up expectations using MockRestServiceServer)
after these beans are created but BEFORE the task is run - is this possible? If not it’s hard to see how to write meaningful integration tests for tasks.
What Ive done for now is a variation on approach (2) above (ie I can run the task more than once / have multiple tests in the same test class)
I'm using
SpringApplication application = new SpringApplication(new Object[] {MyTaskApplication.class, TestConfig.class});
TestConfig is defined with #TestConfiguration in the test class and contains mock beans etc overriding the actual beans
I then use
application.addListeners()
to add a ContextRefreshedEventListener which allows me to set expectations on mocks (or execute jdbc calls) after the beans are created but before the task is run.
(I have a generic Listener class that allows me to pass in the behaviour as a lambda or method reference per bean)
Then run the task with
application.run(args);
(can use different args in different tests)
I can also pass "--spring.cloud.task.closecontext_enable=false" as an argument to keep the application open if i want to verify mocks / db state after the test runs. In this case I close it manually at the end of the test.
If this seems a sensible approach it might be useful if Spring Cloud Task itself provided some sort of generic listener or hook to allow the setting of test state between bean creation and task execution.

When and where must I initialize the spring context?

I'm a noob when using Spring and I have a doubt.
When and where must I initialize the spring context?
Right now I am initializing the context when I'm going to use something like a properties file:
ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("myContext.xml");
But I have read that the Spring context must be initialized in the entry point of my program (Main.java) and pass it as argument in the necessary methods.
Is this true?
As #MarounMaroun said, it really depends on what are you trying to do.
When people use Spring they usually build the entire application to take advantage of what Spring has to offer. That is to say, they put everything in the Spring context, configure it, and let it wire all the things together when starting. So in order to be useful, the application needs to load the Spring context before doing anything else.
For a standalone application you do the initialization in the main method.
When main is called, you first initialize the Spring context, and once the context is fully loaded you retain a reference to it and make it available where needed.
If it makes sense to initialize the Spring context at a later time or in another class you can do that too, but as I said, most applications need the context initialized to be able to function so that's why they initialize it as early as possible, in the main method, and that's probably the recommendation you have read.
If you are talking about a web application, you should do it web.xml
Loading context in Spring using web.xml
If it's a test, things are different:
spring junit load application context for tests
In both cases, you don't need an explicit main.java

Stopping Invokation of Spring Quartz Job on spring context loading

My application has got multiple Jobs which needs to be executed programatically when user wants.
I have implemented all the Jobs using MethodInvokingJobFactoryBean and the issue is whenever my spring context gets loads up all the Jobs gets fired.
How to stop the execution of Job on spring context loading ??
Thanks in advance
Ajay
I assume you have problem because your job calls beans which has not been initialized?
Then you will be interested in depends-on attribute on bean element.
You can also set startupDelay property on SchedulerFactoryBean.

Resources