Spring: ApplicationContextAware has value, but #Autowired does not - java

I opened a question some hrs ago, which got marked as a duplicate, however it was not a duplicate of the marked question, whatever.
Since then, I managed to get some things done, and work stuff out, so here is my question:
I was trying to #Autowire a spring bean into another one, however my problem was that the #Autowired field was always null, depsite of the fact that they were both managed beans and worked correctly by themselves.
I found out, that you can reach the ApplicationContext in a bean by implementing the ApplicationContextAware interface, which I did. It was called and the right context was given to it.
This way, I can call getBean() on the context, which returns the bean I wanted to #Autowire in the first place, which is a yaay, but this seems like a workaround for a bigger problem.
Can you help me what might be wrong? I tried #Autowiring both as field, method and constructor parameter, none worked. These beans are both singleton beans and are used as basis for HesianServiceExporter, in order to reach them from another servlet.
I guess is I'm missing some crucial config information here, but I can't see why a field injection would not work, while at the same time an interface implementation does.
Is it a case, where the bean which I want to #Autowire is not ready yet, so it can't be injected?
As some of you requested, here is my code. Don't know how it helps, but:
#Service(Persistence.NAME)
public class PersistenceBean implements Persistence, ApplicationContextAware {
ApplicationContext context;
#Override
public User getUser() {
User user = new User();
user.setEmail(context.getBean(HelloWorld.class).getText());
return user;
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
}
And my context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:annotation-config />
<context:component-scan base-package="hu.bme.sch.qpa" annotation-config="true"/>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource"
ref="dataSource"/>
<property name="packagesToScan"
value="hu.bme.sch.qpa.global.entities"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">
update
</prop>
<prop key="hibernate.dialect">
org.hibernate.dialect.PostgreSQL95Dialect
</prop>
</props>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost:5432/test"/>
<property name="username" value="qpapp_server_user"/>
<property name="password" value="root"/>
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven/>
<bean id="persistenceExceptionTranslationPostProcessor" class=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
</beans>
And lastly, my ApplicationInitializer is annotated like this:
#ImportResource("/WEB-INF/app-core-servlet.xml")
#SpringBootApplication(scanBasePackages = "hu.bme.sch.qpa")
#EnableWebMvc
#Configuration
#EnableAutoConfiguration
public class CoreStarter extends SpringBootServletInitializer {
public static void main(String[] args) throws Exception {
SpringApplication.run(CoreStarter.class, args);
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
}
}
And here is HelloWorld bean, which is (what the name would suggest) a really simple bean. It's in the same package as PersistenceBean:
#Service(HelloWorld.NAME)
public class HelloWorldBean implements HelloWorld {
#Override
public String getText() {
return "Hello World!!!! I'm remoted";
}
}
Thanks in advance.

Okay, I got it... Boy did it took some time.
So, as it turns out, the context I described didn't include the one that caused the problem, but I didn't want to spam the thread with my whole module.
The missing part is that I'm remoting these beans, just and only the ones that have trouble with Autowiring (I didn't know that at the time).
The way I remoted them was I wrote an implementation to the BeanDefinitionRegistryPostProcessor.
The problem with this was that I instantiated the remote beans as soon as the function of the interface got invoked, which means: before Spring normally would instantiate the beans I want to remote => too early.
Me calling the getBean() too early meant that at the of instantiating the bean, the AutowiredCapableBeanPostProcessor (or sg. like this) was not registered in the list of factories and I didn't have control of it either.
===================================TL;DR=================================
The solution was that in the Remote Exporter bean, when the postProcessBeanDefinitionRegistry() function got invoked, I just simply saved the Registry, and implemented the InstantiationAwareBeanPostProcessor and did the actual remoting when postProcessAfterInstantiation() got invoked => When the bean has been instantiated the "normal" way => the Autowiring will be done, as well as the remote bean will be created.
Sorry for stealing your time, I really appreciate it.

Related

Building standalone Spring Boot app with hibernate connection

I'm trying to build a simple application, which connects with database and saves some data in it, let's say once per hour. I found some tutorials on pages like baeldung, but their solutions doesn't work for me.
Here is my configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">
<context:component-scan base-package="io.github.steve"/>
<!-- Step 4: Add support for conversion, formatting and validation support -->
<mvc:annotation-driven/>
<!-- Step 5: Define Spring MVC view resolver -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="messages"/>
</bean>
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/articles?useSSL=false"/>
<property name="user" value="root"/>
<property name="password" value=""/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="20"/>
<property name="maxIdleTime" value="30000"/>
</bean>
<bean id="sessionFactoryXXX" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="packagesToScan" value="io.github.steve.webscraping.domain"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="myTransactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactoryXXX"/>
</bean>
<tx:annotation-driven transaction-manager="myTransactionManager"/>
</beans>
ArticlesDaoImpl:
#Repository
public class ArticlesDaoImpl implements ArticlesDao {
#Autowired
SessionFactory sessionFactory;
#Override
public List<Article> getAllArticles() {
Session session = sessionFactory.getCurrentSession();
Query<Article> query = session.createQuery("from Article order by uploadDate", Article.class);
return query.getResultList();
}
#Override
public void addArticle(Article article) {
Session session = sessionFactory.getCurrentSession();
session.persist(article);
}
}
ArticlesServiceImpl:
#Service
public class ArticlesServiceImpl implements ArticlesService {
#Autowired
private ArticlesDao articlesDao;
#Override
#Transactional
public List<Article> getAllArticles() {
return articlesDao.getAllArticles();
}
#Override
#Transactional
public void addArticle(Article article) {
articlesDao.addArticle(article);
}
#Override
#Transactional
public void addArticles(List<Article> articles) {
articles.stream().forEach(articlesDao::addArticle);
}
}
And now:
First of all, I don't know where should I put my xml config file.
I have no idea how to build my Main.class. I want to Autowire ArticlesService to Main class and run a method from it. When i use just SpringApplication.run(Main.class, args), it loads and finishing with exit code 1.
Main app:
#SpringBootApplication
#EnableScheduling
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
ScheduledTasks:
#Component
public class ScheduledTasks {
#Autowired
ArticlesService articlesService;
private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
#Scheduled(cron = "* * * * *")
public void reportCurrentTime() {
articlesService.addArticles(new MkyongWebScraper().getArticlesList());
}
}
I'm really new in Spring and I know this question is pretty wide, but I can't find any suitable sources for my tasks. What am I doing wrong?
I am afraid the code you are writing, especially the XML config does not take advantage of the easier and more convenient offered with Spring Boot, and Spring Boot 2.
To generate the skeleton of your project, go to Spring Boot Initializer. You can choose the dependencies you want (in your case, it should "JPA" which is based on Spring Data JPA) and then you can download a zip with your project.
You might want to have a look at Spring Boot documentation. There are also some pretty interesting videos to "get started with Spring Boot" on youtube..
Once you have your project, you can add Spring Data JPA code...
Spring Boot documentation has a section about Spring Data JPA, but you can also find more info in the documentation of Spring Data JPA project.
Best of luck
I already solved my problem. I just didn't understood Spring enough. For people like me I recommend Spring in Action by Craig Walls.

spring #Transactional with jdbcTemplate in Java [duplicate]

I'm new to Spring and I'm wondering if its possible to use numerous transaction managers in the same application?
I have two data access layers - one for both of the databases. I'm wondering, how do you go about using one transaction managers for one layer and different transaction manager for the other layer. I don't need to perform transactions across both databases - yet. But I do need perform transactions on each database individually. I've created an image to help outline my problem:
Here is my application context configuration:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="cheetah.repositories" />
<tx:annotation-driven />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="accounts" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
Here is an example that uses this configuration:
#Repository
public class JpaAccountRepository implements AccountRepository {
#PersistenceContext(unitName = "cheetahAccounts")
private EntityManager accountManager;
#Override
#Transactional
public Account findById(long id) {
Account account = accountManager.find(Account.class, id);
return account;
}
}
So for the account repository, I want to use an entity manager factory with the persistence unit set to accounts. However, with my BusinessData Repository, I want to use an entity manager factory with a different persistence unit. Since I can only define one transaction manager bean, how can I go about using different transaction managers for the different repositories?
Thanks for any help.
Where you use a #Transactional annotation, you can specify the transaction manager to use by adding an attribute set to a bean name or qualifier. For example, if your application context defines multiple transaction managers with qualifiers:
<bean id="transactionManager1"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory1" />
<qualifier value="account"/>
</bean>
<bean id="transactionManager2"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory2" />
<qualifier value="businessData"/>
</bean>
You can use the qualifier to specify the transaction manager to use:
public class TransactionalService {
#Transactional("account")
public void setSomethingInAccount() { ... }
#Transactional("businessData")
public void doSomethingInBusinessData() { ... }
}
This Spring Jira entry discusses the issue a bit:
https://jira.spring.io/browse/SPR-3955
I think it could be one transaction manager per connection if you're not using two-phase commit. You just need to create two transaction managers and inject them with the appropriate connection.
But I must ask the question: why do you think you need two transaction managers? You can have more than one database connection. The DAOs that use the connections can and should be instantiated by different services, each of which can be annotated with their own transactional settings. One manager can accommodate both. Why do you think you need two?

#Transactional don't work, maybe bad configuration for sessionfactory.getCurrentSession() [duplicate]

I'm getting the above exception with Spring3 and Hibernte4
The following is my bean xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<context:annotation-config/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/GHS"/>
<property name="username" value="root"/>
<property name="password" value="newpwd"/>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.example.ghs.model.timetable</value>
</list>
</property>
</bean>
<bean id="baseDAO"
class="com.example.ghs.dao.BaseDAOImpl"/>
</beans>
My BaseDAO class looks like this
public class BaseDAOImpl implements BaseDAO{
private SessionFactory sessionFactory;
#Autowired
public BaseDAOImpl(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
#Override
public Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}
}
The following code throws the exception in the title
public class Main {
public static void main(String[] args){
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("dao-beans.xml");
BaseDAO bd = (BaseDAO) context.getBean("baseDAO");
bd.getCurrentSession();
}
}
Does anyone have an idea about how to solve this problem?
getCurrentSession() only makes sense inside a scope of transaction.
You need to declare an appropriate transaction manager, demarcate boundaries of transaction and perform data access inside it. For example, as follows:
<bean id = "transactionManager" class = "org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name = "sessionFactory" ref = "sessionFactory" />
</bean>
.
PlatformTransactionManager ptm = context.getBean(PlatformTransactionManager.class);
TransactionTemplate tx = new TransactionTemplate(ptm);
tx.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus status) {
// Perform data access here
}
});
See also:
10. Transaction Management
13.3 Hibernate
I came across same problem and got solved as below
Added #Transactional on daoImpl class
Added trnsaction manager in configuration file:
<tx:annotation-driven/>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
I'll just add something that took me some time to debug : don't forget that a #Transactional annotation will only work on "public" methods.
I put some #Transactional on "protected" ones and got this error.
Hope it helps :)
http://docs.spring.io/spring/docs/3.1.0.M2/spring-framework-reference/html/transaction.html
Method visibility and #Transactional
When using proxies, you should apply the #Transactional annotation
only to methods with public visibility. If you do annotate protected,
private or package-visible methods with the #Transactional annotation,
no error is raised, but the annotated method does not exhibit the
configured transactional settings. Consider the use of AspectJ (see
below) if you need to annotate non-public methods.
Which package u have put the BaseDAOImpl class in.. I think It requires a package name similar to the one u have used in the application context xml and it requires a relevant annotation too.

Running <jdbc:initialize-database> at the beginning of context creation

I need to execute SQL script before PropertyPlaceholderConfigurer is initialized in Spring's context, as soon as application properties are stored in the database and this script should insert them. But currently placeholder is initialized earlier, which leads to errors.
Is there a way to execute <jdbc:initialize-database data-source="dataSource" ... before <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" ... in Spring?
Or is there a way to initialize placeholderConfig bean later? I tried to use depends-on, lazy-init attributes for this bean, but it didn't help. Thanks in advance.
Another solution without creating any Bean:
If you've got one <jdbc:initialize-database /> you can add this property depends-on="org.springframework.jdbc.datasource.init.DataSourceInitializer#0" to your bean <bean id="placeholderConfig" />
If you have more than one <jdbc:initialize-database /> adapt the #0.
Here is how I solved that. I created a class Initializer. This class in its constructor executes plain old sql statements (java.sql.Statement), creates table (if it doesn't exist), and inserts properties (if they are not there). The dataSource bean is passed in the context to this constructor, and placeholderConfig bean uses depends-on="initializerBean". So, properties appear in the database before they are used.
This script
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc">
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath:database/drop_schema.sql" />
<jdbc:script location="classpath:database/create_schema.sql" />
<jdbc:script location="classpath:database/sample_data.sql"/>
</jdbc:initialize-database>
<!-- Other bean definitions -->
</bean>
is essentially a shortcut to
<bean class="org.springframework.jdbc.datasource.init.DataSourceInitializer" id="dataSourceInitializer">
<property name="databasePopulator" ref="resourceDatabasePopulator"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="resourceDatabasePopulator"
class="org.springframework.jdbc.datasource.init.ResourceDatabasePopulator">
<property name="scripts">
<array>
<value>classpath:database/drop_schema.sql</value>
<value>classpath:database/create_schema.sql</value>
<value>classpath:database/sample_data.sql</value>
</array>
</property>
</bean>
Note that I've added id to the DataSourceInitializer bean. Now you can reference it in PropertyPlaceholderConfigurer's depends-on attribute. That way you declare that your PropertyPlaceholderConfigurer should be created after DataSourceInitializer.
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="dataSourceInitializer"/>
In my case db was initialized after the LocalContainerEntityManagerFactoryBean had been created and Hibernate was unable to validate my schema.
The documentation explains how to deal with these problems:
http://static.springsource.org/spring/docs/3.0.0.RC3/reference/html/ch12s09.html
12.9.1.1 Initialization of Other Components that Depend on the Database
Our use case was arguably even more complex. We're using flyway for database migrations and it needs to be started before the entityManagerFactory is created. The problem for us was that <jdbc:initialize-database /> was only used in our migration tests and thus initialized in a different application context than flyway and the entityManagerFactory. So we couldn't simply use L. BIZE answer and let our flyway bean depend on org.springframework.jdbc.datasource.init.DataSourceInitializer#0 because it might not exist (i.e. in production it doesn't exist). We ended up creating a custom factory bean like this:
class OptionalBeanInitializer extends AbstractFactoryBean implements BeanFactoryAware {
private String beanName;
private BeanFactory beanFactory;
#Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
#Override
public Class<?> getObjectType() {
return OptionalBeanInitializer.class;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
#Override
protected Object createInstance() throws Exception {
if (beanFactory.containsBean(beanName)) {
// Initialize
beanFactory.getBean(beanName);
}
return new OptionalBeanInitializer();
}
}
Which we could use to depend on our optional dependency like this:
<bean id="optionalDataSourceInitializer" class="com.x.y.z.OptionalBeanInitializer">
<property name="beanName" value="org.springframework.jdbc.datasource.init.DataSourceInitializer#0"/>
</bean>
<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate" depends-on="optionalDataSourceInitializer">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"
depends-on="flyway, optionalDataSourceInitializer">
<property name="dataSource" ref="dataSource"/>
</bean>
The OptionalBeanInitializer will take care of initializing the org.springframework.jdbc.datasource.init.DataSourceInitializer#0 bean only if it exists.
There are two simpler ways to add the depend-on attribute only for test context, and not for production context.
1/Override the bean in the test context.
In our case here is the production context :
<bean id="placeholderConfig" />
And the unit test context :
<bean id="placeholderConfig" depends-on="org.springframework.jdbc.datasource.init.DataSourceInitializer#0" />
Make sure that the unit test context is loaded before the production context and the good placeholderConfig bean will be instanciated, after the jdbc:initialize-database phase.
2/Another way is to use profiles
<beans profile="!test">
<bean id="placeholderConfig" .../>
</beans>
<beans profile="test">
<jdbc:initialize-database data-source="dataSource" .../>
<bean id="placeholderConfig" depends-on="org.springframework.jdbc.datasource.init.DataSourceInitializer#0" .../>
</beans>

Could not autowire field in spring. why?

I keep getting this error, and can't figure out why.. yes I know there many people had similar issues, but reading the answers they got, does not solve my problem.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contactController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.service.ContactService net.controller.ContactController.contactService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [net.service.ContactService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
here is the controller:
#Controller
#SessionAttributes
public class ContactController {
#Autowired
private ContactService contactService;
//methods...
}
the ContactServiceImpl
#Service("contactService")
#Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class ContactServiceImpl implements ContactService {
#Autowired
private ContactDao contactDao;
public ContactServiceImpl() {
}
#Override
#Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public void addContact(Contact contact) {
contactDao.saveContact(contact);
}
#Override
public List<Contact> getContacts() {
return contactDao.getAllContacts();
}
}
the ContactDaoImpl
#Repository("contactDao")
public class ContactDaoImpl implements ContactDao {
#Autowired
private SessionFactory sessionFactory;
#Override
public void saveContact(Contact contact) {
sessionFactory.getCurrentSession().saveOrUpdate(contact);
}
#Override
#SuppressWarnings("unchecked")
public List<Contact> getAllContacts() {
return (List<Contact>) sessionFactory.getCurrentSession().createQuery("from contact c").list();
}
}
and the spring-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:property-placeholder location="classpath:jdbc.properties" />
<context:component-scan base-package="net.controller" />
<tx:annotation-driven transaction-manager="hibernateTransactionManager" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.user}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>net.form.Contact</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
<bean id="hibernateTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
In spring servlet .xml :
<context:component-scan base-package="net.controller" />
(I assumed that the service impl is in the same package as the service interface "net.service")
I think you have to add the package net.service (or all of net) to the component scan. Currently spring only searches in net.controller for components and as your service impl is in net.service, it will not be instantiated by spring.
I was getting this same error and searching for it led me here. My fix appeared to be simply to add #Component annotation to the implementation of the abstract service.
In this case, that would look like:
import org.springframework.stereotype.Component;
...
#Component
public class ContactServiceImpl implements ContactService {
Well there's a problem with the creation of the ContactServiceImpl bean. First, make sure that the class is actually instantiated by debugging the no-args constructor when the Spring context is initiated and when an instance of ContactController is created.
If the ContactServiceImpl is actually instantiated by the Spring context, but it's simply not matched against your #Autowire annotation, try being more explicit in your annotation injection. Here's a guy dealing with a similar problem as yours and giving some possible solutions:
http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/
If you ask me, I think you'll be ok if you replace
#Autowired
private ContactService contactService;
with:
#Resource
#Qualifier("contactService")
private ContactService contactService;
When you get this error some annotation is missing.
I was missing #service annotation on service. When I added that annotation it worked fine for me.
I've faced the same issue today. Turned out to be I forgot to mention #Service/#Component annotation for my service implementation file, for which spring is not able autowire and failing to create the bean.
I had exactly the same problem
try to put the two classes in the same package and add line in the pom.xml
<dependency>
<groupId> org.springframework.boot </groupId>
<artifactId> spring-boot-starter-web </artifactId>
<version> 1.2.0.RELEASE </version>
</dependency>
In java config,make sure you have import your config in RootConfig like this
#Import(PersistenceJPAConfig.class)
Encountered similar error, and tried the solutions earlier mentioned in this post but none of them worked for me. What finally resolved the issue was to set #Autowired(required = false)

Categories