need to understand autowiring beans in spring mvc project? - spring

In my spring mvc+hibernate+annotations project I have these three classes
UserServiceImpl.java
#Service("userService")
public class UserServiceImpl implements UserService {
#Autowired
private UserDAO userDAO;
//other codes
}
UserDAOImpl.java
#Repository("userDAO")
public class UserDAOImpl implements UserDAO {
#Autowired
private SessionFactory sessionFactory;
//other codes
}
RegistrationController.java
#Controller
#RequestMapping("/registration.htm")
public class RegistrationController {
#Autowired
private UserService userService;
//other codes
}
In my dispatcher-servlet.xml I have added the following
<context:annotation-config />
<context:component-scan base-package="com.alw.controllers,com.alw.DAOs,com.alw.services" />
and
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
When I run the project I got the following exceptions:
Error creating bean with name 'registrationController':
Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private com.alw.services.UserService
com.alw.controllers.RegistrationController.userService;
AND
Error creating bean with name 'sessionFactory' defined in ServletContext resource
[/WEB-INF/dispatcher-servlet.xml]:
Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError:
org/apache/commons/pool/impl/GenericObjectPool
CAN SOMEBODY POINT OUT THE WHERE I AM MISSING ?
THIS HAS TAKEN MY ENTIRE DAY TODAY.
EDIT:
I added commons.pool but no result.
I have these set of exceptions.
Error creating bean with name 'registrationController':
Error creating bean with name 'userService':
Error creating bean with name 'userDAO':
Error creating bean with name 'sessionFactory' defined in ServletContext
resource [/WEB-INF/dispatcher-servlet.xml]:
Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError:
Could not initialize class org.hibernate.cfg.AnnotationConfiguration
THANKS....

As duffymo points out, you're missing commons pool from your classpath. As for the other problem, when you say you get error 1 and error 2, do you mean you get two, unrelated errors at different times, or do you get error 1 caused by error 2. If you're seeing them both in the log at the same time, they're probably the same thing, where the second is the cause of the first.
On the other hand, you're making the common mistake of putting all of your service beans into the context belonging to the DispatcherServlet. If you're also declaring the beans in the root context, that could be causing problems for you, too. See this other answer and its linked answers to understand the difference between the root and child contexts in a Spring MVC app:
Why DispatcherServlet creates another application context?
Especially:
Spring-MVC: What are a "context" and "namespace"?

The second one is easy: you're missing the JAR that contains org.apache.commons.pool.impl.GenericObjectPool in your CLASSPATH.
The question is: which class loader? The Java EE app server has a hierarchy of class loaders. I'm guessing that you want to add that JAR to your server /lib directory so it'll be available when the connection pool is set up.
The first one is not clear to me. Try changing your base package to "com.alw" and see if that sorts it out.

Related

Unable to create retry-able datasource for spring boot jdbc

I would like to add the retry feature for database connection certain number of times until the app acquires it. For the I have used the spring-retry on the DataSource but it is not working. It is throwing the following error
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jdbcTemplate' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/JdbcTemplateConfiguration.class]: Unsatisfied dependency expressed through method 'jdbcTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: ExistingValue must be an instance of com.zaxxer.hikari.HikariDataSource
I have seen the debug logs but those are not helpful. Here is the sample source code . kindly help
Note: the dependencies mentioned in build.gradle is required for my app. I have only extracted the retry part.
Your use-case is delaying the start of Spring Boot until your database is up. Spring actually ships with a component that does that. The DatabaseStartupValidator is that component and has existed since about Spring 1.x.
You can add it as a bean and it will wait for further bootstrapping until the database is up.
#Bean
public DatabaseStartupValidator databaseStartupValidator(DataSource dataSource) {
var dsv = new DatabaseStartupValidator();
dsv.setDataSource(dataSource);
return dsv;
}
For a more detailed explanation see this blog post of mine.

NoSuchBeanDefinitionException for bean defined in JavaConfig

I was using XML configuration on my project earlier, and everything was working.
We're moving gradually to java config, so right now I'm at a stage where I'm using a mix of Java and XML configs.
Here's the problem, there is a bean defined in my XML config : beanA.
<bean id="beanA" class="BeanA" />
The class BeanA has an autowired dependency on BeanB.
class BeanA {
#Autowired
BeanB beanB;
}
Earlier, this beanB was also in XML config, and it ran correctly.
Now, I have made this change, and it is no longer working :
#Configuration
class MyConfig {
#Bean
public BeanB beanB() {
return new BeanB();
}
}
Apart from adding #Configuration and #Bean annotations, is there something else required to do that I am missing?
I'm getting the following error :
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'beanB': Unsatisfied dependency expressed through field 'beanA';
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.xxxxxx.yyy.zzzzzzzzzzzz.abc.beanA' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Please note,
I have only moved beanB to be created via java config.
BeanA actually has more dependencies, so I cannot move it to java config at this stage (will be doing proper migration later).
you need to add configuration for BeanB as well in the xml configuration. as when the program is run it loads all the bean definition from xml configuration file. So it looks like BeanB definition is missing in configuraion file.
Spring does not load the beans from the classes annotated with #Configuration unless it has been told to look for classes with this annotation.
To make spring look for these classes, the following must be added in your xml configuration :
<context:component-scan base-package="com.xxxxx.yyy.zzzz">
It will then recursively find and initialize all the beans in the package com.xxxxx.yyy.zzzz.

Initialize bean while project deployment spring

I was asked in one of interview that how we can initialize bean while project deployment in Spring ?
There are several options:
Your bean can implement InitializingBean interface and initialization work can be done inside afterPropertiesSet() method
You can just add a method in a bean class and annotate it with #PostConstruct
You can add method in a bean class and mark it as an init method. Using xml config the bean definition would look like this:
<beans>
<bean id="myBean" class="..." init-method="init"/>
</beans>
And using Java config like this:
#Bean(initMethod="init")
public MyBean myBean() {
return new MyBean();
}
You can also implement your own BeanPostProcessor and provide implementation in postProcessAfterInitialization or postProcessBeforeInitialization methods.
One caveat: all this initialization logic is a part of bean lifecycle, which doesn't mean that it will be invoked during the project deployment.
However if bean is a singleton bean then by default it is created during the spring context start up. I guess it is what you mean by project deployment.

Autowiring fails IllegalArgument un-safe operation exception

I am getting the following exception after upgrading my Spring jars.
org.springframework.web.servlet.DispatcherServlet - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.integration.transformer.HeaderEnricher#4': Cannot create inner bean '(inner bean)' of type [org.springframework.integration.transformer.HeaderEnricher$MessageProcessingHeaderValueMessageProcessor] while setting constructor argument with key [#{partnerHeaderKey}]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#19': Injection of resource dependencies failed; nested exception is java.lang.IllegalArgumentException: Can not set com.follett.fheg.coursemateriallookup.coursematerial.data.dao.PartnerDAO field com.follett.fheg.coursemateriallookup.coursematerial.integration.headerenricher.PartnerHeaderEnricher.partnerDAO to org.springframework.integration.transformer.HeaderEnricher$MessageProcessingHeaderValueMessageProcessor
at org.springframework.beans.factory.support.BeanDefinitionValue Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#19': Injection of resource dependencies failed; nested exception is java.lang.IllegalArgumentException: Can not set com.follett.fheg.coursemateriallookup.coursematerial.data.dao.PartnerDAO field com.follett.fheg.coursemateriallookup.coursematerial.integration.headerenricher.PartnerHeaderEnricher.partnerDAO to org.springframework.integration.transformer.HeaderEnricher$MessageProcessingHeaderValueMessageProcessor
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:306)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1146)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:271)
... 40 more
Caused by: java.lang.IllegalArgumentException: Can not set com.follett.fheg.coursemateriallookup.coursematerial.data.dao.PartnerDAO field com.follett.fheg.coursemateriallookup.coursematerial.integration.headerenricher.PartnerHeaderEnricher.partnerDAO to org.springframework.integration.transformer.HeaderEnricher$MessageProcessingHeaderValueMessageProcessor
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:57)
at java.lang.reflect.Field.set(Field.java:657)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:303)
... 44 more
From what I have read I needed to add #Component annotation to my bean and/or create the in my application context - neither of these approaches have worked. The DAO it is referring to is declared like so <bean id="partnerDAO" class="com.follett.fheg.coursemateriallookup.coursematerial.data.dao.impl.PartnerDAOImpl"/>. If I remove the #Component annotation I get a red line under #Autowired and a message that says "Autowired members must be defined in the valid spring bean (#Component/#Service etc..)", but after doing that i still get the errors.
I am using Spring integration so the bean to auto-wire is defined there.
<integration:header-enricher>
<integration:header name="#{partnerHeaderKey}" method="getPartner">
<bean class="com.follett.fheg.coursemateriallookup.coursematerial.integration.headerenricher.PartnerHeaderEnricher"/>
</integration:header>
</integration:header-enricher>
Any thoughts or help is appreciated! Thank you.
Note: the application runs fine if I drop back down to Spring 2.1.4.RELEASE even without declaring the #Component or <bean> in the application context.
UPDATE
As blackpanther mentions below I need a element in the application context. I failed to mention that I DO Have this <context:component-scan base-package="com.follett.fheg.coursemateriallookup.coursematerial.integration.headerenricher" /> There is another for the DAO's as well <context:component-scan base-package="com.follett.fheg.coursemateriallookup.coursematerial.data.dao" />
Not exactly, just putting the annotation #Component does not mean that that Java class will have it's properties autowired. In order to use the #Component annotation effectively, you must tell Spring where to look for these classes. This is done by the <context:component-scan base-package="package.name" /> tag in your Spring configuration.
I would have a look at this article as it may help you.
You can specify #Qualifier on top of the bean declaration inside the component like below.
#Autowired
#Qualifier("loginService")
private ILoginService loginService;
loginService is the name of the bean in the .xml context file.
I was able to resolve this issue by using #Component annotation as well as modifying the way the beans were created in the context.
For some reason when I moved the <bean class=""> out of the <integration:header> and added a ref-"" attribute it started working just fine. I am getting a different error, but I was able to get the application running.
old way
<integration:header-enricher>
<integration:header name="#{partnerHeaderKey}" method="getPartner">
<bean class="com.follett.fheg.coursemateriallookup.coursematerial.integration.headerenricher.Partner HeaderEnricher"/>
</integration:header>
</integration:header-enricher>
new way
<integration:header-enricher>
<integration:header name="#{partnerHeaderKey}" method="getPartner" ref="myBean">
</integration:header>
</integration:header-enricher>
</integration:chain>
<bean id="myBean" class="com.follett.fheg.coursemateriallookup.coursematerial.integration.headerenricher.PartnerHeaderEnricher"/>

Spring TestContext Framework

i tried to create a test for loading applicationContext.xml using Spring TestContext Framework,the code is pretty simple:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"/applicationContext.xml"})
public class ApplicationContextLoadingTest {
#Autowired
private ApplicationContext applicationContext;
#Ignore
#Test
public void testContext() {
}
}
when i run the test i got the error message:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pollInitializer' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute query
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1338)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
...
any one knows what that means? Thanks
It means exactly what it says: applicationContext.xml contains a bean named pollInitializer, this bean has an initialization method, that method tried to execute some Hibernate query, and the query failed with SQLGrammarException.
So, check Hibernate queries issued by that initialization method.
It means that spring is loading the file applicationContect.xml and is it is failing to setup the bean named pollInitalizer which is defined in that file.
With your test you are attemptinhpg to auto wire an ApplicationContext. That is not really normal. Normally you would auto wire some beans defined in the XML that you caused to be loaded. You don't have to work with the application context directly.

Resources