Spring Boot & Swagger 2 : UnsatisfiedDependencyException - Repository tests not working - spring-mvc

I have a Spring Boot Rest API that I've been working, and I added Swagger and Swagger-UI last week. After that, the tests of the repositories(ONLY tests related with the repository) started to not working and when I run them I get this error:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'documentationPluginsBootstrapper' defined in URL [jar:file:/C:/Users/Ale/.m2/repository/io/springfox/springfox-spring-web/2.3.1/springfox-spring-web-2.3.1.jar!/springfox/documentation/spring/web/plugins/DocumentationPluginsBootstrapper.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webMvcRequestHandlerProvider' defined in URL [jar:file:/C:/Users/Ale/.m2/repository/io/springfox/springfox-spring-web/2.3.1/springfox-spring-web-2.3.1.jar!/springfox/documentation/spring/web/plugins/WebMvcRequestHandlerProvider.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.List<org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 33 more
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webMvcRequestHandlerProvider' defined in URL [jar:file:/C:/Users/Ale/.m2/repository/io/springfox/springfox-spring-web/2.3.1/springfox-spring-web-2.3.1.jar!/springfox/documentation/spring/web/plugins/WebMvcRequestHandlerProvider.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.List<org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 51 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.List<org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 65 more
I don't know why this error is happening, because these tests are not related with Swagger.
The configuration code is like this:
#EnableSwagger2
#SpringBootApplication
public class UserServiceApplication extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
#Bean
public Docket productApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select().apis(RequestHandlerSelectors.basePackage(getClass().getPackage().getName()))
.paths(PathSelectors.any())
.build()
.apiInfo(generateApiInfo());
}
private ApiInfo generateApiInfo() {
return new ApiInfo("User Service", "User Service", "", "", "", "", "");
}
}
The POM file is like this, with Swagger 2.3.1:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${io.springfox.springfox-swagger2}</version>
</dependency>
<!-- Include swagger for API description UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${io.springfox.springfox-swagger-ui}</version>
</dependency>
And the test is very simple:
#RunWith(SpringRunner.class)
#DataJpaTest
#Transactional
public class UserRepositoryTest {
#Autowired
private TestEntityManager entityManager;
#Autowired
private UserRepository userRepository;
#Test
public void whenPersistingAnUserTheUserAndImageAreSaved(){
UserImage userImage = new UserImage("key","URL");
User user = new User("email#mail.com", "pass","name","lastNmae","description","123123",userImage);
User savedUser = userRepository.save(user);
assertNotNull(savedUser.getId());
assertNotNull(savedUser.getUserImage().getId());
}
Could you help me please? The rest of the tests work correctly.
Thanks!

The problem is that your central configuration class UserServiceApplication is setting up Swagger and Spring MVC. When you use #DataJpaTest, you are effectively telling Spring Boot not to load the Spring MVC related infrastructure. But... some of the beans created by #EnableSwagger2 expect the MVC infrastructure to be in place, which is not the case with #DataJpaTest.
Thus, in order to benefit from Spring Boot's test slicing support (i.e., #DataJpaTest), you'll need to move the Swagger and MVC configuration to a separate #Configuration class.

I have answered here as well:
https://stackoverflow.com/a/52670119/8553816.
1. Extend swagger with WebMvcConfigurerAdapter adapter and override addResourceHandlers method like mentioned below along with swagger config methods:
#Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
Note: WebMvcConfigurerAdapter is deprecated in spring 5 so use WebMvcConfigurationSupport in spring 5 and later.
2. Make sure your test class is also annotated with #SpringBootTest, #RunWith(SpringRunner.class) alongwith #datajpatest.
Tip: Create a custom annotation and add bunch of other annotations loke #transactional etc. and use this custom annotation on repo test classes.
3. Its better to have a different spring profile to run test cases and dont forget to annotate the test class with #ActiveProfiles("profileHere").
Hope solution works!

Also, make sure to have your swagger configuration out of the #SpringBootApplication class, including the #EnableSwagger2 annotation:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
#Configuration
#EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {
// ...
}

Related

Why removing WebMvcTest annotation from my test in SpringBoot application causes ComponentScan to fail?

I have a test defined with:
#ComponentScan(basePackages = { ... })
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { AppConfig.class })
#WebMvcTest(secure = false)
public class MyTest extends AbstractJUnit4SpringContextTests {
#Autowired SomeClass target;
#Test public void test() { Assert.assertTrue(target != null); } // MCVE
}
Here's my ContextConfiguration class:
#Configuration
public class AppConfig {
#Bean
#ConfigurationProperties(prefix = "datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
#Bean
ServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
This test works fine, but it wastes a lot of time in MVC initialization due to the #WebMvcTest annotation. This particular test does not require any MVC functionality. The annotation ended up in there as a result of trial-and-error, to get the #Autowired annotation to work correctly. But now I want to remove it.
So... I went ahead and removed the #WebMvcTest annotation. But then the test fails because apparently the #ComponentScan does not have any effect unless #WebMvcTest is present (which I now remember, is the reason I added it).
Here's the actual error message:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type '...' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I tried adding #SpringBootTest but it made no difference.
If instead, I add #EnableAutoConfiguration, I get a different error:
java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
What annotation am I missing?
EDIT:
Why removing WebMvcTest annotation from my test in SpringBoot application causes ComponentScan to fail?
Because you have not annotated the class in a way that Spring's IoC/Dependency injection can work correctly.
Now that the answer is clear, here are a couple of suggestions for you to try. They may or may not work depending upon how your project and dependencies etc are put together.
END EDIT:
This particular test does not require any MVC functionality.
You should consider using one of the more direct auto-configuration annotations for the your tests if you don't need all of MVC but do want auto configuration. For instance, it appears you are testing with some data system. Perhaps the #DataJpaTest or #JdbcTest annotations would provide a more streamlined approach. These will enable auto configuration (IoC and Dependency injection).
What annotation am I missing?
As written above, the annotation you are missing is #Configuration
This is counter intuitive here because this isn't a configuration class. But without an appropriate annotation that enables Dependency injection to occur, this is the only way to get this to work. Why?
From the docs:
public #interface ComponentScan
Configures component scanning directives for use with #Configuration classes.
So your choices are:
Use a different auto config annotation as suggested above
Add the #Configuration annotation

Spring Boot MVC Converter Cannot Autowire Neo4J Data Repositories

I'm needing to #Autowire a Spring Data Neo4J repository into a Spring MVC converter (in Spring Boot), but the MVC configuration gets started before the Data services get started. This results in an #Autowired not found problem. How do I get the Data Services to get started before the MVC so it finds an eligible bean?
I have a project I'm converting from XML Spring config to Spring Boot. Everything is working fine except for the MVC Converters. They are not able to #Autowire Neo4J Repository classes.
If remove the #Autowire of the Repository and hard code in a value, things work as expected with the hack. Other operations in services are using the Repositories just fine. It seems the MVC config is getting started before the Neo4J plumbing can get started and then can't find the right components to tie into. I've looked, but I can't figure out how to get the data config to start before the MVC config.
Here's my base config:
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Toyfiles {
public static void main(String[] args) throws Exception {
SpringApplication.run(Toyfiles.class, args);
}
}
My MVC Config:
#Configuration
public class MVCBeans extends WebMvcConfigurerAdapter {
#Autowired
private StringToBrand stringToBrand;
#Autowired
private BrandToString brandToString;
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(stringToBrand);
registry.addConverter(brandToString);
super.addFormatters(registry);
}
}
The offending Converter:
#Component
public class StringToBrand implements Converter<String, Brand> {
#Autowired
BrandRepository brandRepository;
#Override
public Brand convert(String s) {
return brandRepository.findBrandByName(s);
}
}
The Data config:
#Configuration
#Profile("localEmbeddedDBServer")
#EnableTransactionManagement
#EnableNeo4jRepositories(basePackages = "com.toyfiles.dataservices.")
public class LocalDBConfig extends Neo4jConfiguration {
public LocalDBConfig() {
setBasePackage("com.toyfiles");
}
#Bean
public GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabase("target/graph.db");
}
}
And the Repository:
public interface BrandRepository extends GraphRepository<Brand> {
#Query(value = "MATCH (brand:Brand {name:{0}})-[:PART_OF]->line RETURN line")
public List<Line> getLinesForBrand(String name);
#Query(value = "MATCH (brand:Brand {name:{0}}) DELETE brand")
public void deleteBrandByName(String name);
public Brand findBrandByName(String name);
}
The "interesting" part of the Exception:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'brandRepository': Cannot resolve reference to bean 'neo4jTemplate' while setting bean property 'neo4jTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'neo4jTemplate' defined in class path resource [com/toyfiles/configuration/LocalDBConfig.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.data.neo4j.support.Neo4jTemplate org.springframework.data.neo4j.config.Neo4jConfiguration.neo4jTemplate() throws java.lang.Exception] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'neo4jMappingContext' defined in class path resource [com/toyfiles/configuration/LocalDBConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext#4d49af10: startup date [Mon Sep 29 09:48:25 PDT 2014]; root of context hierarchy
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:336)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1457)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1198)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1021)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:964)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:862)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:481)
... 116 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'neo4jTemplate' defined in class path resource [com/toyfiles/configuration/LocalDBConfig.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.data.neo4j.support.Neo4jTemplate org.springframework.data.neo4j.config.Neo4jConfiguration.neo4jTemplate() throws java.lang.Exception] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'neo4jMappingContext' defined in class path resource [com/toyfiles/configuration/LocalDBConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext#4d49af10: startup date [Mon Sep 29 09:48:25 PDT 2014]; root of context hierarchy
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:597)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1095)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:990)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
... 129 more
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.data.neo4j.support.Neo4jTemplate org.springframework.data.neo4j.config.Neo4jConfiguration.neo4jTemplate() throws java.lang.Exception] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'neo4jMappingContext' defined in class path resource [com/toyfiles/configuration/LocalDBConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext#4d49af10: startup date [Mon Sep 29 09:48:25 PDT 2014]; root of context hierarchy
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:188)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:586)
... 138 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'neo4jMappingContext' defined in class path resource [com/toyfiles/configuration/LocalDBConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext#4d49af10: startup date [Mon Sep 29 09:48:25 PDT 2014]; root of context hierarchy
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1554)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:288)
at com.toyfiles.configuration.LocalDBConfig$$EnhancerBySpringCGLIB$$321222c6.mappingInfrastructure(<generated>)
at org.springframework.data.neo4j.config.Neo4jConfiguration.neo4jTemplate(Neo4jConfiguration.java:135)
at com.toyfiles.configuration.LocalDBConfig$$EnhancerBySpringCGLIB$$321222c6.CGLIB$neo4jTemplate$23(<generated>)
at com.toyfiles.configuration.LocalDBConfig$$EnhancerBySpringCGLIB$$321222c6$$FastClassBySpringCGLIB$$12e74a61.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
at com.toyfiles.configuration.LocalDBConfig$$EnhancerBySpringCGLIB$$321222c6.neo4jTemplate(<generated>)
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:483)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
... 139 more
Caused by: java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext#4d49af10: startup date [Mon Sep 29 09:48:25 PDT 2014]; root of context hierarchy
at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:346)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:333)
at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:307)
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.addPersistentEntity(Neo4jMappingContext.java:69)
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.addPersistentEntity(Neo4jMappingContext.java:49)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:181)
at org.springframework.data.neo4j.mapping.RelationshipInfo.<init>(RelationshipInfo.java:65)
at org.springframework.data.neo4j.mapping.RelationshipInfo.fromField(RelationshipInfo.java:79)
at org.springframework.data.neo4j.support.mapping.Neo4jPersistentPropertyImpl.extractRelationshipInfo(Neo4JPersistentPropertyImpl.java:128)
at org.springframework.data.neo4j.support.mapping.Neo4jPersistentPropertyImpl.<init>(Neo4JPersistentPropertyImpl.java:80)
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.createPersistentProperty(Neo4jMappingContext.java:161)
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.createPersistentProperty(Neo4jMappingContext.java:49)
at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.createAndRegisterProperty(AbstractMappingContext.java:449)
at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.doWith(AbstractMappingContext.java:427)
at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:606)
at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:295)
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.addPersistentEntity(Neo4jMappingContext.java:69)
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.addPersistentEntity(Neo4jMappingContext.java:49)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:181)
at org.springframework.data.neo4j.mapping.RelationshipInfo.<init>(RelationshipInfo.java:65)
at org.springframework.data.neo4j.mapping.RelationshipInfo.fromField(RelationshipInfo.java:79)
at org.springframework.data.neo4j.support.mapping.Neo4jPersistentPropertyImpl.extractRelationshipInfo(Neo4JPersistentPropertyImpl.java:128)
at org.springframework.data.neo4j.support.mapping.Neo4jPersistentPropertyImpl.<init>(Neo4JPersistentPropertyImpl.java:80)
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.createPersistentProperty(Neo4jMappingContext.java:161)
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.createPersistentProperty(Neo4jMappingContext.java:49)
at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.createAndRegisterProperty(AbstractMappingContext.java:449)
at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.doWith(AbstractMappingContext.java:427)
at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:606)
at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:295)
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.addPersistentEntity(Neo4jMappingContext.java:69)
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.addPersistentEntity(Neo4jMappingContext.java:49)
at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:257)
at org.springframework.data.mapping.context.AbstractMappingContext.initialize(AbstractMappingContext.java:373)
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.initialize(Neo4jMappingContext.java:111)
at org.springframework.data.mapping.context.AbstractMappingContext.afterPropertiesSet(AbstractMappingContext.java:363)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1613)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1550)
... 160 more
I used an #Lazy annotation for the repository to delay the reference to the repository since the repository was getting started correctly later in the startup. This allowed the repository reference to be delayed until it was needed and available.
#Autowired
#Lazy
BrandRepository brandRepository;

Spring java based config ResourceLoader

I am new to java-based configuration in spring. I am trying to convert the xml based configuration found here: https://github.com/sps/mustache-spring-view
My problem is the ResourceLoader used by MustacheViewResolver is throwing a null pointer exception. How can I properly load the resource loader provided by spring into this configuration?
#Configuration
#ComponentScan(basePackageClasses = Application.class, includeFilters = #Filter(Controller.class), useDefaultFilters = false)
class WebMvcConfig extends WebMvcConfigurationSupport {
#Bean
public MustacheViewResolver viewResolver() {
MustacheViewResolver resolver = new MustacheViewResolver();
resolver.setPrefix("/WEB-INF/views/mustache/");
resolver.setSuffix("hbs");
resolver.setCache(true);
resolver.setTemplateFactory(new MustacheJTemplateFactory());
return resolver;
}
}
Exception:
Caused by: java.lang.NullPointerException
at org.springframework.web.servlet.view.mustache.java.MustacheJTemplateFactory.getReader(MustacheJTemplateFactory.java:71)
And the line from MustacheJTemplateFactory
Resource resource = resourceLoader.getResource(resourceName);
Please Note: I believe this to be a general question about spring java configuration, and not a specific question about the library I am using. I could be wrong though!
Autowire in the Spring resource loader:
#Autowired
ResourceLoader resourceLoader;
Then set it in your viewResolver() function:
MustacheJTemplateFactory factory = new MustacheJTemplateFactory();
factory.setResourceLoader(resourceLoader);
resolver.setTemplateFactory(factory);

Spring beans injection into jax-ws services

So I already learnt that integration of spring and jax-ws is not an easy thing.
I want to inject a spring bean into jax-ws service, but for some reason I get an exception during the deployment:
Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: java.lang.IllegalArgumentException: javax.servlet.ServletException: com.sun.enterprise.container.common.spi.util.InjectionException: Error creating managed object for class: class org.springframework.web.context.ContextLoaderListener|#]
this is my jax-ws configuration:
<wss:binding url="/ws/users">
<wss:service>
<ws:service bean="#usersWs"/>
</wss:service>
</wss:binding>
<bean id="usersWs" class="love.service.endpoint.implementations.UserServiceImpl" />
And this is my service:
#WebService
public class UserServiceImpl implements UserService{
#EJB
private DBManager dbmanager;
#Override
#WebMethod
public boolean addUser(String name, String password, String email) {
return false;
}
#Override
#WebMethod
public boolean isUsernameAvailable(String username) {
return dbmanager.isLoginAvailable(username);
}
#Override
#WebMethod
public boolean isEmailAvailable(String email) {
return dbmanager.isEmailAvailable(email);
}
}
and finally my bean configuration:
<bean id="dbmanager" class="love.commons.database.DBManager" scope="request">
<aop:scoped-proxy/>
</bean>
I also tried injecting the bean into some controllers and then it works perfectly well.
If I replace #EJB with #Autowired, the application starts, but the service still doesn't work. When I tried sending a message to it, my only response was the following:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
<faultcode>S:Server</faultcode>
<faultstring>Error creating bean with name 'scopedTarget.dbmanager': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.</faultstring>
</S:Fault>
</S:Body>
</S:Envelope>

Autowired dependency not injected in Aspect in Spring MVC

I am not able to #Autowire the Service Layer Instance in Aspect. In Aspect the reference to the #Autowired bean is NULL and it throws NullPointerException. Any help will be much appreciated. I think, I messed up with configuration.
Following is my servlet-context.xml:
<!-- Activates various annotations to be detected in bean classes -->
<context:annotation-config />
<context:spring-configured />
<!-- Scans the classpath of this application for #Components to deploy as beans -->
<context:component-scan base-package="xx.yy" />
<!-- an #AspectJ aspect will be interpreted as an aspect by Spring AOP and beans in the context will be advised accordingly -->
<aop:aspectj-autoproxy />
<beans:bean id="loggingAspect" class="xx.yy.aop.aspects.LoggingAspect" />
<beans:bean id="authenticationAspect" class="xx.yy.aop.aspects.AuthenticationAspect" />
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
Following is my Aspect:
#Configurable
#Component
#Aspect
public class AuthenticationAspect {
private static final Logger logger = LoggerFactory.getLogger(AuthenticationAspect.class);
#Autowired
private LoginService loginService;
//....
}
Here is my controller using the #Authentication Annotation defined above:
#Controller
#RequestMapping("/user")
public class UsersController {
#Autowired
private UserService userService;
#Authenticate
#RequestMapping(value="/{userId}/profile", method=RequestMethod.GET)
public String displayUser(WebRequest webRequest, #PathVariable("userId") String userId, Model model) {
User user = userService.findUser(Long.valueOf(userId));
model.addAttribute("user", user);
model.addAttribute("AccordionMenuTab","5");
model.addAttribute("selectedLink","profile");
return "profile";
}
I am getting following exception:
Oct 8, 2011 3:12:48 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet appServlet threw exception
java.lang.NullPointerException
at xx.yy.controller.UsersController.displayUser_aroundBody1$advice(UsersController.java:28)
at xx.yy.controller.UsersController.displayUser(UsersController.java:1)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:662)
See this piece of the documentation:
7.8.3 Configuring AspectJ aspects using Spring IoC
When using AspectJ aspects with Spring applications, it is natural to both want and expect to be able to configure such aspects using Spring. The AspectJ runtime itself is responsible for aspect creation, and the means of configuring the AspectJ created aspects via Spring depends on the AspectJ instantiation model (the 'per-xxx' clause) used by the aspect.
The majority of AspectJ aspects are singleton aspects. Configuration of these aspects is very easy: simply create a bean definition referencing the aspect type as normal, and include the bean attribute 'factory-method="aspectOf"'. This ensures that Spring obtains the aspect instance by asking AspectJ for it rather than trying to create an instance itself. For example:
<bean id="profiler" class="com.xyz.profiler.Profiler"
factory-method="aspectOf" />
For anyone looking for a java based bean configuration, Using java reflections I could archive the same
#Bean
public ExceptionAspectHandler exceptionAspectHandler(){
try
{
//noinspection JavaReflectionMemberAccess
Method method = ExceptionAspectHandler.class.getMethod("aspectOf" );
return (ExceptionAspectHandler) method.invoke(null);
}
catch( IllegalAccessException | InvocationTargetException | NoSuchMethodException e )
{
logger.log( Level.SEVERE, "Error creating bean : ", e );
}
return null;
}
Since the aspectOf() method is not available during compile time we cannot create the bean by just calling the method. That is why XML configuration is able to handle it.
Alternatively simpler approach
#Bean
public ExceptionAspectHandler exceptionAspectHandler()
{
return Aspects.aspectOf( ExceptionAspectHandler.class );
}
This also does work.

Resources