Spring NullPointerException while injecting Map - spring

I am trying to inject a Map into a UtilityClass. I have created a Map Bean and I am injecting it using #Resource annotation.
#Configuration
class MyConfiguration {
#Bean
Map<String, String> testMap(){
def map = [:] // Using groovy
// Putting things into map
map
}
}
#Component
class MyUtilityClass {
#Resource(name="testMap")
Map<String, String> testMap
}
I am getting following error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testMap' defined in com.my.company.config.MyConfiguration: Initialization of bean failed; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
.....
Caused by: java.lang.NullPointerException
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:571) ~[spring-core-4.1.5.RELEASE.jar:4.1.5.RELEASE]
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:490) ~[spring-core-4.1.5.RELEASE.jar:4.1.5.RELEASE]
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:474) ~[spring-core-4.1.5.RELEASE.jar:4.1.5.RELEASE]
Am I doing something wrong here while injecting the Map. Not sure why the NPE is caused?
UPDATE -
So created a class and added the Map as an attribute of that class. And injected that class as a Bean. It worked correctly and it could inject the Class with the Map in it.
#Configuration
class MyConfiguration {
#Bean
Testclass testClass(){
def map = [:] // Using groovy
// Putting things into map
new TestClass(testMap: map)
}
}
class TestClass {
Map<String, String> testMap
}
So seems like the issue is in the Map being injected.

Related

Unsatisfied dependency expressed through field on factory-bean

I am getting the following error :
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'factoryBO': Unsatisfied dependency expressed through field 'cleanupProvider': No qualifying bean of type [com.spring.factory.interfaces.impl.CleanupProvider] found for dependency [com.spring.factory.interfaces.impl.CleanupProvider]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.spring.factory.interfaces.impl.CleanupProvider] found for dependency [com.spring.factory.interfaces.impl.CleanupProvider]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:350)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
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:775)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.spring.factory.runner.FactoryRunner.main(FactoryRunner.java:10)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.spring.factory.interfaces.impl.CleanupProvider] found for dependency [com.spring.factory.interfaces.impl.CleanupProvider]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1398)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1051)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1018)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:570)
... 15 more
Source code :
FactoryBo.java
I added #Autowired on top od CleanupProvider class; I did it for corresponding interface as well; But it didn't work for me;
package com.spring.factory.bo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.spring.factory.interfaces.ICleanupProvider;
import com.spring.factory.interfaces.impl.CleanupProvider;
#Component
public class FactoryBO {
#Autowired
CleanupProvider cleanupProvider;
public void getFactoryProviderLogic() {
cleanupProvider.performCleanup("Algo");
}
}
CleanupProvider.java
package com.spring.factory.interfaces.impl;
import com.spring.factory.interfaces.ICleanupProvider;
import com.spring.factory.interfaces.ICleanupStrategy;
public class CleanupProvider implements ICleanupProvider {
#Override
public String performCleanup(String strate) {
System.out.println("Received Text:::"+ strate);
return strate+":"+"Received";
}
#Override
public void registerStrategy(ICleanupStrategy normalizeStrategy) {
System.out.println("NormalizationProvider:::registerStrategy::");
}
}
CleanupProviderFactory .java
So, here I want to make the existing method createInstance as a factory method;
package com.spring.factory.interfaces.impl;
import com.spring.factory.interfaces.ICleanupProvider;
import com.spring.factory.interfaces.ICleanupProviderFactory;
public class CleanupProviderFactory implements ICleanupProviderFactory {
public ICleanupProvider createInstance() {
ICleanupProvider normalizeProvider = new CleanupProvider();
normalizeProvider.registerStrategy(new CleanupStrategy());
return normalizeProvider;
}
public static ICleanupProviderFactory createFactoryInstance() {
return new CleanupProviderFactory();
}
}
ICleanupProvider.java
package com.spring.factory.interfaces;
public interface ICleanupProvider {
public String performCleanup(String algo);
public void registerStrategy(ICleanupStrategy strategy);
}
ICleanupProviderFactory.java
package com.spring.factory.interfaces;
public interface ICleanupProviderFactory {
}
package com.spring.factory.runner;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.spring.factory.bo.FactoryBO;
public class FactoryRunner {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
FactoryBO bo = context.getBean(FactoryBO.class);
bo.getFactoryProviderLogic();
context.close();
}
}
spring.xml
<context:annotation-config/>
<context:component-scan base-package="com.spring.factory.bo"></context:component-scan>
<bean id="cleanupProviderFactory"
class="com.spring.factory.interfaces.impl.CleanupProviderFactory"
factory-method="createFactoryInstance"></bean>
<bean id="cleanupProvider"
class="com.spring.factory.interfaces.ICleanupProvider"
factory-bean="cleanupProviderFactory" lazy-init="default" factory-method="createInstance"></bean>
Is there anything I missed?
You can add #Component to your CleanupProvider class:
#Component
public class CleanupProvider { ...}
Or define a method to create your been like so:
#Bean
public CleanupProvider getCleanupProvider() {
return new CleanupProvider();
}
An explanation of which annotation to use is best described here: Understanding Spring #Autowired usage
I believe you just missed providing your CleanupProvider class a #Bean annotation (like #Component, #Service, #Repository, #Controller) so that bean factory recognizes it and is able to Autowire, like this Spring documentation tells you to do so.
EDIT
Ok, so have seen your spring.xml, I assume the mistake was you were declaring the bean as ICleanupProvider class, which is the interface, whereas FactoryBO autowires the implementation (CleanupProvider).

A ServletContext is required to configure default servlet handling

I am trying to figure out a issue for some days but no luck. I came across this issue but not able figure out what is the problem since i am not doing any test here. java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultServletHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'defaultServletHandlerMapping' threw exception; nested exception is java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1119) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1014) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
I am using spring boot
#ComponentScan
#EnableAutoConfiguration
public class Application {
.....
}
public class ApplicationWebXml extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
#Configuration
#AutoConfigureAfter
public class WebConfigurer implements ServletContextInitializer, EmbeddedServletContainerCustomizer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
EnumSet<DispatcherType> disps = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC);
initCachingHttpHeadersFilter(servletContext, disps);
initStaticResourcesProductionFilter(servletContext, disps);
initGzipFilter(servletContext, disps);
}
Now the problem is coming in TypeToJsonMetadataConverter bean definition in the following #Configuration classes.
#Configuration
public class EntityRestMvcConfiguration extends RepositoryRestMvcConfiguration {
#Bean
public TypeToJsonMetadataConverter typeToJsonMetadataConverter() {
return new TypeToJsonMetadataConverter(typeConfiguration(),
entityLinks());
}
#Bean
public TypeConfiguration typeConfiguration() {
return new TypeConfiguration();
}
}

error springboot #autowired dependency

I try do a fill repository with metrics in spring boot, but I have the problem that when I execute I recive error.
This is my error:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'actuatorMetricsPrinter' defined in file [ActuatorMetricsPrinter.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.util.Collection]: : No qualifying bean of type [org.springframework.boot.actuate.endpoint.PublicMetrics] found for dependency [collection of org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.boot.actuate.endpoint.PublicMetrics] found for dependency [collection of org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:747)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1115)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
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.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:706)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
at hello.Application.main(Application.java:14)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.boot.actuate.endpoint.PublicMetrics] found for dependency [collection of org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1118)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:919)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:862)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:811)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:739)
... 18 common frames omitted
And this is my code when I recive error:
#Autowired
public DummyController(ActuatorMetricsPrinter metricsPrinter) {
this.metricsPrinter = metricsPrinter;
}
I have a class ActuatorMetricsPrinter that show the metrics but I have a problem when try fill this repository
*EDIT *
#Component
public class ActuatorMetricsPrinter {
private MetricRepository repository;
private static final String TEMPLATE = "Metric: %s [%s]";
private Collection<PublicMetrics> publicMetrics = null;
public String printAllMetrics() {
StringBuilder sb = new StringBuilder();
for (PublicMetrics pm : publicMetrics) {
sb.append("Public Metric: " + pm.getClass().getName());
sb.append("\n\n");
for (Metric<?> m : pm.metrics()) {
sb.append(String.format(TEMPLATE, m.getName(), m.getValue().toString()));
sb.append("\n");
}
}
return sb.toString();
}
#Autowired
public void MetricExporterService(MetricRepository repository) {
this.repository = repository;
}
And
#Controller
public class DummyController {
private final ActuatorMetricsPrinter metricsPrinter;
#Autowired
public DummyController(ActuatorMetricsPrinter metricsPrinter) {
this.metricsPrinter = metricsPrinter;
}
#RequestMapping(value = "/customMetrics", method = RequestMethod.GET)
#ResponseBody
public String printMetrics() {
return metricsPrinter.printAllMetrics();
}
#Bean
public ActuatorMetricsPrinter publicMetrics() {
return new ActuatorMetricsPrinter();
}
}
Thank you very much!
Spring beans factory not found a bean Collection<PublicMetrics> publicMetrics for autowarid; try to create a list of PublicMetrics
see : Spring autowire a list
Auto-wiring a List using util schema gives NoSuchBeanDefinitionException
In your case the actual problem is initializing the constructor for ActuatorMetricsPrinter. You have it Autowired to take in a Collection so Spring is trying to find the set of PublicMetrics beans to use as a collection and it cannot find any. Here is the error in what you provided above that points to that. I ran into the same issue myself at one point.
No qualifying bean of type
[org.springframework.boot.actuate.endpoint.PublicMetrics] found for
dependency [collection of
org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at
least 1 bean which qualifies as autowire candidate for this
dependency.
From the Spring Docs on Autowired:
In case of a Collection or Map dependency type, the container will
autowire all beans matching the declared value type. In case of a Map,
the keys must be declared as type String and will be resolved to the
corresponding bean names.
Since the PublicMetrics are not declared as beans I think the right way to do it is by autowiring to a MetricRepository. See this link and the Exporting Metrics section there as a reference. There is a link to a sample application. Here is some modified code that you can use.
#Autowired
public MetricExporterService(MetricRepository repository) {
this.repository = repository;
}
public String printAllMetrics() {
StringBuilder sb = new StringBuilder();
for (Metric metric : repository.findAll()) {
sb.append(String.format(TEMPLATE, metric.getName(), metric.getValue().toString()));
}
return sb.toString();
}

Context loader control with Phased interface in Spring

I am trying to take under control the context loading process. As I can read in Spring reference documentation I determined to use Phased interface provided by Spring.
When starting, the objects with the lowest phase start first, and when
stopping, the reverse order is followed. Therefore, an object that
implements SmartLifecycle and whose getPhase() method returns
Integer.MIN_VALUE would be among the first to start and the last to
stop. At the other end of the spectrum, a phase value of
Integer.MAX_VALUE would indicate that the object should be started
last and stopped first (likely because it depends on other processes
to be running). When considering the phase value, it’s also important
to know that the default phase for any "normal" Lifecycle object that
does not implement SmartLifecycle would be 0. Therefore, any negative
phase value would indicate that an object should start before those
standard components (and stop after them), and vice versa for any
positive phase value.
public interface Phased {
int getPhase();
}
public interface SmartLifecycle extends Lifecycle, Phased {
boolean isAutoStartup();
void stop(Runnable callback);
}
Only I want load two controllers in phased after all others have been initialized.
To achieve this behaviour I have implemented the Phased Interface in both Spring Components.
#Service to be initialized at firstly.
#Service
public class BatchTaskController implements Phased{
#Autowired
private ActorService actorService;
#Autowired
private SessionFactory sessionFactory;
public BatchTaskController(){
this.batch();
}
public void batch(){
//TO DO...
}
#Override
public int getPhase() {
return 1;
}
}
#Controller to be initialized after batch task #Service.
#Controller
public class MainController implements Phased{
#Autowired
private ActorService actorService;
#Autowired
private SessionFactory sessionFactory;
#RequestMapping(value = {"/", "/index"})
public String showHome(HttpServletRequest request) {
//TO DO
return "index";
}
#Override
public int getPhase() {
return 2;
}
}
ActorService #Service not implement Phased Interface. Therefore I guess as I could read in the Spring Reference article exposed above that ActorService #Service is starting before than previous #Controllers because ActorService #Service phase valor was 0 by default.
But, when I deploy my app i get the next NullPointerException error.
04-04-2014 08:34:10,286 AM ERROR ContextLoader:331 - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'batchTaskController' defined in file [E:\Desarrollo\Spring\pjcomspringehcache\target\pjcomspringehcache-1.0-SNAPSHOT\WEB-INF\classes\com\pjcom\pjcomspringehcache\BatchTaskController.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.pjcom.pjcomspringehcache.BatchTaskController]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1076)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1021)
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:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4738)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5158)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:726)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:702)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:697)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:579)
at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1744)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.uti
l.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:744)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.pjcom.pjcomspringehcache.BatchTaskController]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:164)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1069)
... 26 more
Caused by: java.lang.NullPointerException
at com.pjcom.pjcomspringehcache.BatchTaskController.batch(BatchTaskController.java:32)
at com.pjcom.pjcomspringehcache.BatchTaskController.<init>(BatchTaskController.java:23)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
... 28 more
Why?
SOLUTION
#Service to be initialized at firstly.
#Service
public class BatchTaskController implements Phased{
#Autowired
private ActorService actorService;
#Autowired
private SessionFactory sessionFactory;
#PostConstruct
public void batch(){
//TO DO...
}
#Override
public int getPhase() {
return 1;
}
}

Spring error when trying to manage several classes that share a common base class?

Im currently using Spring 3.0.x ..
Im wondering what's wrong with these structures,
where i would like to manage the subclasses but not the parent classes.
I have 2 child DAOs extending the BaseDAO :
public abstract class BaseDAO<K, E> {
....
}
#Repository
public class UserDAO extends BaseDAO<String, User> {
....
}
#Repository
public class ApprovalDAO extends BaseDAO<String, Approval> {
....
}
And i have the services like this, with hierarchies like this :
public abstract class BaseService<K, E extends BaseEntity, D extends BaseDAO<K, E>> {
#Autowired
protected D dao;
....
}
public abstract class BaseCommonService<K, E extends BaseCommonEntity, D extends BaseDAO<K, E>> extends BaseService<K,E,D> {
....
}
#Service
public class UserService extends BaseCommonService<String, User, UserDAO> {
....
}
When trying to inject the userservice object to my application, it throws error like this :
Exception in thread "main"
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name
'testEntities': Injection of autowired
dependencies failed; nested exception
is
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private
com.primetech.module.common.service.UserService
com.primetech.module.purchase.app.TestEntities.userService;
nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name
'userService': Injection of autowired
dependencies failed; nested exception
is
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: protected
com.primetech.core.parent.BaseDAO
com.primetech.core.parent.BaseService.dao;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type
[com.primetech.core.parent.BaseDAO] is
defined: expected single matching bean
but found 2: [userDAO, approvalDAO]
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1064)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:574)
at
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at
org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
at
org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:93)
at
com.primetech.module.purchase.app.TestEntities.main(TestEntities.java:81)
Caused by:
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private
com.primetech.module.common.service.UserService
com.primetech.module.purchase.app.TestEntities.userService;
nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name
'userService': Injection of autowired
dependencies failed; nested exception
is
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: protected
com.primetech.core.parent.BaseDAO
com.primetech.core.parent.BaseService.dao;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type
[com.primetech.core.parent.BaseDAO] is
defined: expected single matching bean
but found 2: [userDAO, approvalDAO]
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:507)
at
org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:283)
... 13 more Caused by:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name
'userService': Injection of autowired
dependencies failed; nested exception
is
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: protected
com.primetech.core.parent.BaseDAO
com.primetech.core.parent.BaseService.dao;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type
[com.primetech.core.parent.BaseDAO] is
defined: expected single matching bean
but found 2: [userDAO, approvalDAO]
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1064)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:838)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:780)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:697)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
... 15 more Caused by:
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: protected
com.primetech.core.parent.BaseDAO
com.primetech.core.parent.BaseService.dao;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type
[com.primetech.core.parent.BaseDAO] is
defined: expected single matching bean
but found 2: [userDAO, approvalDAO]
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:507)
at
org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:283)
... 26 more Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type
[com.primetech.core.parent.BaseDAO] is
defined: expected single matching bean
but found 2: [userDAO, approvalDAO]
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:790)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:697)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
... 28 more
I tried changing this section, removing the #Repository annotation :
#Repository
public class ApprovalDAO extends BaseDAO<String, Approval> {
....
}
into this :
public class ApprovalDAO extends BaseDAO<String, Approval> {
....
}
And things run without error, but then, the approvalDAO isnt managed by the spring anymore, and cannot be injected later by #Autowired
Any suggestions on how i can solve this problem ?
Autowiring works only if there is exactly one implementation bean of the specific type present in the Spring Context. I'd assume that using the generic D extends BaseDao leads to a situation where Spring is trying to autowire instances of BaseDao instead of UserDao and ApprovalDao. Because you both UserDao and ApprovalDao implement BaseDao, Spring context contains multiple implementations of BaseDao and cannot decide which one should be used.
Spring is trying to tell this to you in the stack trace
org.springframework.beans.factory.NoSuchBeanDefinitionException:
__No unique bean of type__ [com.primetech.core.parent.BaseDAO] is defined:
expected single matching bean but found 2: [userDAO, approvalDAO]
You could try to test this by defining the dao in the concrete service using the actual dao type e.g.
public abstract class BaseService<K, E extends BaseEntity, D extends BaseDAO<K, E>> {
private final D dao;
protected BaseService(D dao) {
this.dao = dao;
}
}
public class UserService extends BaseService<K, User, UserDao<K, User>> {
#Autowired
public UserService(UserDao dao) {
super(dao);
}
}
I'd continue by defining interfaces for UserDao and ApprovalDao so that dependencies are on interfaces and not implementations. The daos may still have a common super interface and their implementations may be based on the BaseDao to avoid unnecessary duplication.
In the example I've defined the injected Dao in the constructor because I assume that the same dao instance should be used throughout the lifetime of the service and the service cannot exist without the dao set. In my opinion, a constructor argument communicates this contract better. Furthermore it might make the class a bit more testable and maintainable.

Resources