I am implementing Spring Security in project. I have reached an impasse stuck here since hours.
I am getting this error
Error creating bean with name 'org.springframework.security.authentication.dao.DaoAuthenticationProvider#0': Cannot resolve reference to bean 'UserDAOImpl' while setting bean property 'userDetailsService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myUserDetailService' is defined
The project setup is very simple
spring-security.xml
<authentication-manager>
<authentication-provider user-service-ref="myUserDetailService">
</authentication-provider>
</authentication-manager>
dispatcher-servlet.xml
<context:component-scan base-package="app.com,app.com.controller,app.com.dao,app.com.service,app.com.model"/>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"
p:basename="messages"/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/view/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
ApplicationContext.xml
<context:annotation-config />
<!-- <context:property-placeholder> XML element automatically registers a new PropertyPlaceholderConfigurer
bean in the Spring Context. -->
<context:property-placeholder location="classpath:database.properties" />
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="hibernateTransactionManager"/>
<!-- Creating DataSource -->
<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>
<!-- To persist the object to database, the instance of SessionFactory interface is created.
SessionFactory is a singleton instance which implements Factory design pattern.
SessionFactory loads hibernate.cfg.xml and with the help of TransactionFactory and ConnectionProvider
implements all the configuration settings on a database. -->
<!-- Configuring SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>app.com.model.User</value>
<value>app.com.model.Roles</value>
<value>app.com.BaseEntity</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
</props>
</property>
</bean>
<!-- Configuring Hibernate Transaction Manager -->
<bean id="hibernateTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
CustomUserDetailsService.java
#Service("myUserDetailService")
#Transactional
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private UserDAO userDAO;
/*#Override
public UserDetails loadUserByUsername(String arg0)
throws UsernameNotFoundException, DataAccessException {
// TODO Auto-generated method stub
return null;
}
}
I also tried declaring the bean in both dispatcher-servlet.xml & application-context.xml it doesn't work
checked the context-component base package. It is scanning all the other classes present just fine. When I remove myUserDetailService from authentication provider the server starts just fine without any error.
I am really tired. Can anyone please help me in fixing this?
the reason why you got this working after moving the definitions to your context file is because in spring, the definitions inside the dispatcher servlet are only visible to mvc, and definitions inside context are global (to servlet and security), here is a page where its clearly explained https://weblogs.java.net/blog/sgdev-blog/archive/2014/07/05/common-mistakes-when-using-spring-mvc
phew... got it working.
Moved
<context:component-scan base-package="app.com,app.com.controller,app.com.dao,app.com.service,app.com.model"/>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"
p:basename="messages"/>
from dispatcher-servlet to application-context.xml
Would anyone care to tell why it started working?
Related
I am new to Spring framework; need some clarifications on how the SessionFactory object Dependency injection is working in below code.
spring-servlet.xml
<context:annotation-config />
<context:component-scan base-package="com.employee" />
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<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="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
p:password="${jdbc.password}" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:employee.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
EmployeeDAOImpl.java
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
#Repository
public class EmployeeDAOImpl implements EmployeeDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public void addEmployee(EmployeeForm employee) {
sessionFactory.getCurrentSession().save(employee);
}
}
How is the sessionFactory getting initialized with a SessionFactory object here?
What I understand
In the sprng-servlet.xml file, the DI of sessionFactory is happening in the below code:
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Now, if I open the source code for the class org.springframework.orm.hibernate3.HibernateTransactionManager, then I can see the below section:
private SessionFactory sessionFactory;
public HibernateTransactionManager(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
afterPropertiesSet();
}
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
public SessionFactory getSessionFactory(){
return this.sessionFactory;
}
which means the sessionFactory class variable of org.springframework.orm.hibernate3.HibernateTransactionManager has been initializd.
Now my Query:
In my code posted above, how is the sessionFactory of class EmployeeDAOImpl.java getting initialized? I can't find any relation between the sessionFactory of class org.springframework.orm.hibernate3.HibernateTransactionManager (where DI is happening) and the sessionFactory of class EmployeeDAOImpl.java (which I wrote). Then how is it working?
Please explain - totally confused !!!
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:employee.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
You have defined the session factory bean in you context file. During the application bootstrap, the spring context is loaded and this session factory bean is initialized by spring as a singleton instance.
<context:annotation-config />
<context:component-scan base-package="com.employee" />
#Autowired
private SessionFactory sessionFactory;
And since you have enabled the annotation-config and component-scan and declared #Autowired in your DAOImp, this is the reason Spring knows the place to inject the session factory bean properly.
This configuration is enabled the transaction manager annotation.
Example:
#Transactional
public void addEmployee(EmployeeForm employee){...}
Here is the suggestion.
Transactional annotation is better to be placed in service layer instead of DAO layer. You need to make sure the annotation is placed on the concrete class unless you use the interface-proxy in your component-scan.
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
This piece of configuration is set the transaction manager bean which lets transaction manager knows which session factory it needs to manage with.
Therefore the configuration of bean
id="transactionManager" sets the transaction manager with the proper hibernate session factory.
tx:annotation-driven configuration enables the annotation-based transaction manager in code level.
Hope the explanation is helpful for you. :)
I´ve my hibernate configuration inside my spring-context, but after a little time of use I´m getting the too many connections error. Here is my code:
Spring context:
<!-- Beans Declaration -->
<bean id="Usuarios" class="com.proximate.model.Usuarios"/>
<!-- Service Declaration -->
<bean id="UsuariosService" class="com.proximate.service.UsuariosService">
<property name="usuariosDAO" ref="UsuariosDAO" />
</bean>
<!-- DAO Declaration -->
<bean id="UsuariosDAO" class="com.proximate.dao.UsuariosDAO">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
<bean id="DataSource" 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/mydb" />
<property name="user" value="user" />
<property name="password" value="password" />
<property name="maxPoolSize" value="50" />
<property name="maxStatements" value="0" />
<property name="minPoolSize" value="5" />
</bean>
<!-- Session Factory Declaration -->
<bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="DataSource" />
<property name="annotatedClasses">
<list>
<value>com.proximate.model.Usuarios</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
<!-- Enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager"/>
<context:annotation-config />
<!-- Transaction Manager is defined -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory"/>
</bean>
and here is how I use my session factory inside my dao:
private SessionFactory sessionFactory;
private HibernateTemplate hibernateTemplate;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
Query query = hibernateTemplate.getSessionFactory().getCurrentSession().createSQLQuery("SELECT ID FROM usuarios");
Integer cantidad = new Integer(((BigInteger) query.uniqueResult()).intValue());
Why is my code opening so many connections. I heard that using a HibernateUtil class to load a session after logging might be what I need, but how do you implement it when using spring??
Thanks in advance!!
I don't know much about hibernate itself, but i think closing the session might help.
That's how JPAs EntityManager works - you have to close it to close underlaying connection.
It looks like your hibernate query is global? I would guess the cause is probably because it is not contained in a method with a transactional annotation around it.
I have simple application with following folder structure:
ProjFolder
|-----src
|----------packagename
|---------------{sourcefiles}
|----------META-INF
|---------------{beans.xml}
|---------------{hibernate.cfg.xml}
|---------------{EntityMapping.hbm.xml}
here is the part of beans.xml Spring config file:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:./META-INF/jdbc.properties" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:./META-INF/hibernate.cfg.xml" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>classpath:./META-INF/EntityMapping.hbm.xml</value>
</list>
</property>
</bean>
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
when i start my unit tests i getting following exception:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'wrapperClass' defined in class path resource
[META-INF/beans.xml]: Cannot resolve reference to bean 'wrapperClassField'
while setting constructor argument; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'xmlBooksource' defined in class path resource
[META-INF/beans.xml]: Cannot resolve reference to bean
'sessionFactory' while setting bean property 'sessionFactory'; nested
exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'sessionFactory' defined in class path
resource [META-INF/beans.xml]: Invocation of init method failed;
nested exception is java.io.FileNotFoundException: class path resource
[classpath:/META-INF/EntityMapping.hbm.xml] cannot be opened because it does not exist
The same exception is thrown when i type
<property name="mappingResources">
<list>
<value>EntityMapping.hbm.xml</value>
</list>
</property>
Why spring cant find this file and how i must fill its location to make this code work?
Thanks in advance.
Have you tried removing the classpath: prefix? In looking at the Hibernate code, the mappingResources setter expects passes the strings to new ClassPathResource(String). This expects classpath resources already. The string then gets passed to ClassLoader.getResourceAsStream(String). None of this code would strip the "classpath:" prefix from the front of the resource string.
I'm not sure the error message is consistent with the beans.xml content you posted.
In the error you have
[classpath:/META-INF/EntityMapping.hbm.xml]
which isn't the same as
classpath:./META-INF/EntityMapping.hbm.xml
Notice the missing "." at the beginning in the error.
The second beans.xml configuration, should probably produce a different error message with:
[classpath:EntityMapping.hbm.xml]
This would be searching for the file in the root of your compiled application (jar, war, exploded, what have you).
I have successfully configure Hibernate 4 with Spring 3.1. My applicationContext.xml file is inside web-inf folder and has the following hibernate cofiguration:
<!-- Session Factory Declaration -->
<bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="DataSource" />
<!--
<property name="annotatedClasses">
<list>
<value>iltaf.models.Levels</value>
</list>
</property>
-->
<property name="mappingLocations" value="classpath:iltaf/models/*.hbm.xml" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager"/>
<!-- Transaction Manager is defined -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory"/>
</bean>
</beans>
and I have separate hibernate.cfg.xml file inside my src folder. I am using Eclipse Juno Java EE version.
I'm trying to create a persistance project so it can be re-used by some other projects I'm building on top. I.e it will be used by a web service/spring mvc project and by standalone jar which does some file processing.
I've used hibernate with spring mvc before but never as a standalone executable java jar so I have everything setup and working(application context) :
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- Enable annotation style of managing transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Root Context: defines shared resources visible to all other web components -->
<!-- HIBERNATE -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:spring.properties" />
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.databaseurl}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="acquireIncrement" value="5" />
<property name="idleConnectionTestPeriod" value="60"/>
<property name="maxPoolSize" value="100"/>
<property name="maxStatements" value="50"/>
<property name="minPoolSize" value="10"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list> <value>com/project/utility/persistence/mapping/TestProp.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- END HIBERNATE -->
</beans>
When I test it from main class everything looks ok with mapping/dependencies :
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("appCtx.xml");
}
What I want to do next is to build few dao classes which will get some data and I'd build some interface above that so it can be re-used by both webservice and processing tool as a jar(maven dependency).
In order to build dao classes I need sessionFactory to be != null always. How do I do this?
There are many approaches to this. One solution I use is to use the javax.persistence.PersistenceContext annotation. Spring will respect this annotation and inject a proxy to a thread local EntityManager. Provided your DAO is created by Spring this allows access to the entity manager from within your DAO.
public class DAO {
private EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}
#Repository
public class MyDAO {
#Autowired
private SessionFactory sessionFactory;
// ...
}
and add the MyDAO bean to the context XML file, or simply add the following lines to this file:
<context:annotation-config />
<context:component-scan base-package="one.of.the.parent.packages.of.your.dao" />
I am using JUnit 4 to test Dao Access with Spring (annotations) and JPA (hibernate). The datasource is configured through JNDI(Weblogic) with an ORacle(Backend). This persistence is configured with just the name and a RESOURCE_LOCAL transaction-type
The application context file contains notations for annotations, JPA config, transactions, and default package and configuration for annotation detection.
I am using Junit4 like so:
ApplicationContext
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="workRequest"/>
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="${database.target}"/>
<property name="showSql" value="${database.showSql}" />
<property name="generateDdl" value="${database.generateDdl}" />
</bean>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>workRequest</value>
</property>
<property name="jndiEnvironment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">t3://localhost:7001</prop>
</props>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
JUnit TestCase
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class AssignmentDaoTest {
private AssignmentDao assignmentDao;
#Test
public void readAll() {
assertNotNull("assignmentDao cannot be null", assignmentDao);
List<Assignment> assignments = assignmentDao.findAll();
assertNotNull("There are no assignments yet", assignments);
}
}
regardless of what changes I make I get:
No unique bean of type [javax.persistence.EntityManager] is defined
Any hint on what this could be. I am running the tests inside eclipse.
Your Spring context has a bean definition using LocalContainerEntityManagerFactoryBean. This creates an EntityManagerFactory, not an EntityManager.
AssignmentDao needs to get itself wired with an EntityManagerFactory.
Alternatively, you can replace the LocalContainerEntityManagerFactoryBean with a LocalEntityManagerFactoryBean, which will create an EntityManager directly. However, you need to be careful with that one, it has some downsides. See that part of the Spring docs for a full explanation of the options.
It's confusing, because the naming conventions of JPA and Spring overlap each other, so naming these classes is a real bugger.