Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring Boot multiple context refreshes #410

Open
simonwibberley opened this issue Sep 2, 2020 · 9 comments
Open

Spring Boot multiple context refreshes #410

simonwibberley opened this issue Sep 2, 2020 · 9 comments

Comments

@simonwibberley
Copy link

Hi there,

I'm having trouble running a spring boot payload in a shared context - jobs throw the error:

GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once

I had encountered this error before and thought it was the result of auto configuration classes being included under the component scan for in the job XML, which cause a refresh request when they configure (?). However, I've been careful to purge any such auto configurations from the component scan path, and the error persists.

Could anyone shed some light on what might really be happening?

Running JQM 2.2.1

Many thanks,

Simon

com.enioka.jqm.api.JobRunnerException: event handler could not be loaded or run: com.enioka.jqm.handler.AnnotationSpringContextBootstrapHandler
	at com.enioka.jqm.tools.PayloadClassLoader.launchJar(PayloadClassLoader.java:207)
	at com.enioka.jqm.tools.JavaJobInstanceTracker.run(JavaJobInstanceTracker.java:127)
	at com.enioka.jqm.tools.RunningJobInstance.actualRun(RunningJobInstance.java:180)
	at com.enioka.jqm.tools.RunningJobInstance.run(RunningJobInstance.java:85)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.enioka.jqm.tools.PayloadClassLoader.launchJar(PayloadClassLoader.java:203)
	... 4 more
Caused by: java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once
	at org.springframework.context.support.GenericApplicationContext.refreshBeanFactory(GenericApplicationContext.java:266)
	at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:636)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:521)
	at com.enioka.jqm.handler.AnnotationSpringContextBootstrapHandler.run(AnnotationSpringContextBootstrapHandler.java:153)
	... 9 more```
@simonwibberley
Copy link
Author

Just confirmed the same error happens on JQM 2.2.4

@marcanpilami
Copy link
Contributor

The stacktrace tells us context refresh is called twice. JQM takes care never to call refresh twice with a simple lock mechanism so there is indeed something evil afoot. Cannot preproduce on my side, so could you please provide the following:

  • does it occur to all Spring launches?
  • is this context shared by multiple jobs, and do they all have the issue? Does the launch order matter?
  • ideally, could you provide your job configuration & a test job on which the issue occurs?

BTW, auto config should not be an issue - they are scanned as any other. If you look at the jqm-test-spring-1 demo/test in the source, you'll see that this is a fully-fledged Spring boot application with two @configuration classes.

@simonwibberley
Copy link
Author

Thanks @marcanpilami - I now believe it's to do with how I'm [mis]using the CommandLineRunner interface - we have multiple of them, and spring runs all of them which isn't what I want, and may be triggering multiple refreshes.

Is there a way to run a payload through JQM in my IDE? That way I could debug the refresh call directly.

Many thanks,

Simon

@simonwibberley
Copy link
Author

Our payload now appears to be working correctly under 2.2.5 - whatever you did (I noticed cleanThread() appeared in AnnotationSpringContextBootstrapHandler ?) may have done the trick!

Many thanks!

Simon

@simonwibberley
Copy link
Author

@marcanpilami curiously, if I switch to PostgreSQL back end the refresh issue reappears! I thought upgrading to 2.2.5 fixed it, but it is perhaps a side effect from using the H2 default.

Could there be some kind of concurrency issue?

@marcanpilami
Copy link
Contributor

We had made no change to the AnnotationSpringContextBootstrapHandler in 2.2.5. It seems indeed to be a concurrency issue - as if we tried to init twice despite the lock. The issue may actually be either in JQM or in Spring, as they may do some dark magic with class loaders. What version are you using? I'll try to reproduce with this version and pgsql. (and if you have a minimal job showing the issue it would help us a lot). Thanks!

@marcanpilami
Copy link
Contributor

marcanpilami commented Oct 4, 2020

And I realise I've missed your testing question - currently the testers (https://jqm.readthedocs.io/en/jqm-all-2.2.5/jobs/testing_payloads.html) do not allow to specify runners and event interceptors as they are designed to handle only the most common cases. As Spring is widely used, it may be a good idea to add support - API to be determined. I've opened a new ticket for this (#414)

@simonwibberley
Copy link
Author

@marcanpilami thanks for you attention on this.

We're using Spring Boot 2.1.5.RELEASE.

To note quickly, submitting job requests in quick succession appears to result in only one, or a small subset, of them reaching payload execution, which also feels like a concurrency issue.

I'll put together a minimal example to reproduce this week.

Kind regard,

Simon

@marcanpilami
Copy link
Contributor

@simonwibberley any chance on the reproduction?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants