My repository can't initialize automatically while using Spring Data JPA - spring

I am trying to add spring data jpa to my spring-mvc web project after exploring a couple of tutorials. But I found my repository can't initialize automatically, I got NullPointerException in my service class. Please see my following sample code:
My repository:
public interface SubjectRepository extends JpaRepository<PSubject, String>{
public Page<PSubject> findByType(String title, Pageable pageable);
public Page<PSubject> findByType(String title);
public Page<PSubject> findByMacaddress(String macaddress, Pageable pageable);
public Page<PSubject> findByMacaddress(String macaddress);
public Page<PSubject> findByUri(String uri);
}
My controller:
#Controller
#RequestMapping("/subject")
public class VPSubjectController
{
....
#RequestMapping("/{id}.htm")
public ModelAndView detail(#PathVariable String id)
{
ModelAndView mav = new ModelAndView("subject/detail");
PSubject subject = subjectService.get(id);
....
}
}
My Service:
#Service("subjectService")
public class SubjectServiceImpl extends VPService implements SubjectService
{
#Autowired
private SubjectRepository subjectRepository;
......
#Override
#Transactional(propagation=Propagation.REQUIRED, readOnly=true)
public PSubject get(String subject) {
PSubject subObj = subjectRepository.findOne(subject);
return subObj;
}
.....
My configuration:
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
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/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
....
<jpa:repositories base-package="com.mypacke.repository" repository-impl-postfix="Impl" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"/>
....
I found in this line subjectRepository.findOne(subject) ,subjectRepository is null,
My question is similar this post

#Autowired annotation is activated by the statement:
<context:component-scan base-package="base.package"/>
If u do that, it would be initialized

Related

Spring dependency config problems

Hello guys,
I am new to Spring and currently I am working on a web project in which I use Spring MVC and Spring dependency injection. I have three classes. UserService, HomeController and User. In HomeController I invoke UserService's fetchUser method which returns me a new Instance of the User class. It is a simple logic I use to reproduce my real project problem. I am not using any database in this simple project. When I invoke the fetchUserMethod I am getting a NullPointerException. I am using Glassfish 4.0. Could you please help me ?
Thank you !
Here is my web.xml
`<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/aplicationContext.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>`
Here is my applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="userService" class="services.UserService"/>
<bean id="homeController" class="controllers.HomeController">
<property name="userService" ref="userService"/>
</bean>
</beans>
Here is my servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Enables the Spring MVC #Controller programming model -->
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<context:component-scan base-package="controllers"/>
</beans:beans>
Here is my HomeController class
#Controller
public class HomeController {
private UserService userService;
#RequestMapping(value = "/home")
public ModelAndView homePage(HttpServletRequest request, HttpServletResponse response, HttpSession session){
User user = userService.fetchUser();
return new ModelAndView("home", "displayName", user.getUserName());
}
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
}
Here is my User class
public class User {
private String userName;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
Here is my UserService class
public class UserService {
public User fetchUser(){
User user = new User();
user.setUserName("test");
return user;
}
}
You miss the #Autowired annotation in your HomeController:
#Autowired
private UserService userService;
Remove homeController bean defintiion.
Since you are using <context:component-scan base-package="controllers"/> there is no need to declare homeController bean - it will be created automatically because it's annotated with annotation #Controller.
Autowire UserService into HomeController using#Autowired` annotation. There are 3 ways you can do it:
field injection:
#Autowired
private UserService userService;
setter injection
#Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
constructor injection:
#Autowired
public HomeController(UserService userService) {
this.userService = userService;
}
Preferred way is to always use constructor injection
Remove UserService getters and setters in HomeController.
In the end, HomeController class should look like:
#Controller
public class HomeController {
private final UserService userService;
#Autowired
public HomeController(UserService userService) {
this.userService = userService;
}
#RequestMapping(value = "/home")
public ModelAndView homePage(HttpServletRequest request, HttpServletResponse response, HttpSession session){
User user = userService.fetchUser();
return new ModelAndView("home", "displayName", user.getUserName());
}
}
This way Eclipse marks the default constructor line with error. If I remove the default constructor glassfish says it cannot initialize UserService because there is no default constructor.
public class UserService {
public UserService(){}
private final UserDao userDao;
#Autowired
public UserService(UserDao userDao){
this.userDao = userDao;
}
public User fetchUser(){
User user = userDao.fetchUser();
return user;
}
}

Spring JPA 2.0 Repository / Factory not working

I'm trying to implement a custom java Spring JPA repository, as described in the Spring documentation.
It seems that my spring config insists on creating the repositories in the standard way, instead of using the given MyRepositoryFactoryBean, giving me
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.myapp.repository.impl.DocumentRepositoryImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.myapp.repository.impl.DocumentRepositoryImpl.<init>()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:83)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1006)
... 43 more
Caused by: java.lang.NoSuchMethodException: com.myapp.repository.impl.DocumentRepositoryImpl.<init>()
at java.lang.Class.getConstructor0(Class.java:2730)
at java.lang.Class.getDeclaredConstructor(Class.java:2004)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:78)
I'm using Spring 3.2.2-RELEASE and spring-data-jpa-1.3.2-RELEASE, which is the latest if I'm correct. Here's my spring config:
<?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"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
<import resource="spring-repository-config.xml"/>
<import resource="spring-security-config.xml"/>
<context:component-scan base-package="com.myapp.web.controller"/>
<context:component-scan base-package="com.myapp.webservice.controller"/>
And here's the spring-repository-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/data/jpa"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd">
<repositories base-package="com.myapp.repository"
factory-class="com.myapp.repository.impl.MyRepositoryFactoryBean"/>
<!-- entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager" -->
If've added debug breakpoints in all the methods of the com.myapp.repository.impl.MyRepositoryFactoryBean class, but these were not called.
The basic interface, just like in the example
package com.myapp.repository.impl;
#NoRepositoryBean
public interface MyRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
The base implementation:
package com.myapp.repository.impl;
#NoRepositoryBean
public class MyRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements MyRepository<T, ID> {
private EntityManager entityManager;
public MyRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
super(domainClass, entityManager);
// This is the recommended method for accessing inherited class dependencies.
this.entityManager = entityManager;
}
public void sharedCustomMethod(ID id) {
// implementation goes here
}
}
And the factory:
package com.myapp.repository.impl;
import java.io.Serializable;
import javax.persistence.EntityManager;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
public class MyRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> {
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new MyRepositoryFactory(entityManager);
}
private static class MyRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {
private EntityManager entityManager;
public MyRepositoryFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
protected Object getTargetRepository(RepositoryMetadata metadata) {
return new MyRepositoryImpl<T, I>((Class<T>) metadata.getDomainType(), entityManager);
}
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
// The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory
// to check for QueryDslJpaRepository's which is out of scope.
return MyRepositoryImpl.class;
}
}
}
My repositories interfaces are defines as:
package com.myapp.repository;
public interface DocumentRepository { // extends MyRepository<Document, Long>
public Document findByDocumentHash(String hashCode);
public Document findById(long id);
}
And the implementation is
package com.myapp.repository.impl;
import java.io.Serializable;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
public class DocumentRepositoryImpl<Document, ID extends Serializable> extends MyRepositoryImpl<Document, Serializable> {
private static final long serialVersionUID = 1L;
public DocumentRepositoryImpl(Class<Document> domainClass, EntityManager entityManager) {
super(domainClass, entityManager);
}
And I use these repositories as autowired refernces in my controllers:
package com.myapp.web.controller;
#Controller
#RequestMapping(value = "/documents")
public class DocumentController {
#Autowired
private DocumentRepository documentRepository;
#RequestMapping(method = RequestMethod.GET)
public ModelAndView list(HttpServletRequest request) {
this.documentRepository. ...
}
I've looked at various resources on the web like this one, but I can't tell the difference with my code. Any hints are more than welcome!
You need default constructor for com.myapp.repository.impl.DocumentRepositoryImpl
public DocumentRepositoryImpl(){}
Spring first instantiate the beans that you declare in the app context (in your case) by calling the default constructor( no parameters ) and than uses setters to inject other beans.

Spring 3.2 AOP - Intercepting methods by annotation

I'm trying to intercept any method tagged w/ a custom annotation and the reason you read this is because I can't get it to work. I've been following simple examples but can't get it to work.
Here is my code.
MyAnnotation.java:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface MyAnnotation {
String value() default "";
String key() default "";
String condition() default "";
}
MyAspect.java:
#Aspect
public class MyAspect {
#Pointcut(value="execution(public * *(..))")
public void anyPublicMethod() { }
#Around("anyPublicMethod() && #annotation(myAnnotation)")
public Object process(ProceedingJoinPoint jointPoint, MyAnnotation myAnnotation) throws Throwable {
System.out.println("In AOP process");
return 5; //jointPoint.proceed();
}
}
spring-config.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:c="http://www.springframework.org/schema/c"
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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-3.2.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.2.xsd">
...
<context:component-scan base-package="com.myapp">
<context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="myAspect" class="com.myapp.annotation.MyAspect" />
...
MyComponent.java:
#Component
public class MyComponent {
#MyAnnotation(value="valtest", key="keytest", condition="contest")
public int add(int i, int j) {
System.out.println("Executing annotation.add");
return i+j;
}
}
Test code:
final MyComponent m = new MyComponent();
assertTrue(5 == m.add(0, 1)); // Here m.add(...) always returns 1 instead of 5.
As a side note I've tried to define my pointcut many different ways, all with and without the use of the anyPublic() method and its execution pointcut, but none of those worked for me:
#Around("#annotation(com.myapp.annotation.MyAnnotation)")
public Object process(ProceedingJoinPoint jointPoint) throws Throwable { .. }
#Around(value="#annotation(myAnnotation)", argNames="myAnnotation")
public Object process(ProceedingJoinPoint jointPoint, MyAnnotation myAnnotation) throws Throwable { .. }
#Around("execution(* com.myapp.*.*(..)) && #annotation(com.myapp.annotation.MyAnnotation)")
public Object process(ProceedingJoinPoint jointPoint) throws Throwable { .. }
What am I doing wrong?
In your test code, you are not allowing Spring to create your MyComponent, but instead, you are using the new operator. You should be accessing MyComponent from Spring's ApplicationContext.
public class SomeTest {
public static void main(String[] args) throws Exception {
final ApplicationContext appContext = new ClassPathXmlApplicationContext("spring-config.xml");
final MyComponent myComponent = appContext.getBean(MyComponent.class);
//your test here...
}
}
If you do not get your component from Spring, how do you expect it to be proxied?

Spring Security - UserDetailsService implementation - Login Fails

I'm quite new to spring and i'having this issue with spring security.
Actually it only works without my custom UserDetailsService implementation.
Account and Role Objects
#Entity
#Table(name="ACCOUNT", uniqueConstraints = {#UniqueConstraint (columnNames = "USERNAME"), #UniqueConstraint (columnNames = "EMAIL")})
public class Account implements Serializable {
private static final long serialVersionUID = 2872791921224905344L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="ID")
private Integer id;
#Column(name="USERNAME")
#NotNull
private String username;
#Column(name="PASSWORD")
#NotNull
private String password;
#Column(name="EMAIL")
#NotNull
#Email
private String email;
#Column(name="ENABLED")
private boolean enabled;
#ManyToMany(cascade= CascadeType.ALL)
#JoinTable(name="ACCOUNT_ROLE", joinColumns = {#JoinColumn (name="ID_ACCOUNT")}, inverseJoinColumns ={ #JoinColumn (name="ID_ROLE")})
private Set<Role> roles = new HashSet<Role>(0);
Role
#Entity
#Table(name="ROLE", uniqueConstraints={#UniqueConstraint (columnNames="NAME")})
public class Role implements Serializable{
private static final long serialVersionUID = -9162292216387180496L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name = "NAME")
#NotNull
private String name;
#ManyToMany(mappedBy = "roles")
private Set<Account> accounts = new HashSet<Account>(0);
The adapter for the UserDetails
#SuppressWarnings({ "serial", "deprecation" })
public class UserDetailsAdapter implements UserDetails {
private Account account;
public UserDetailsAdapter(Account account) {this.account = account;}
public Account getAccount() {return account;}
public Integer getId(){return account.getId();}
public String getEmail () {return account.getEmail();}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
for (Role r :account.getRoles()) {
authorities.add(new GrantedAuthorityImpl(r.getName()));
}
return authorities;
}
The custom UserDetailsService
#Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
#Inject AccountDao accountDao;
#Inject RoleDao roleDao;
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
Account account= accountDao.findByUsername(username);
if(account==null) {throw new UsernameNotFoundException("No such user: " + username);
} else if (account.getRoles().isEmpty()) {
throw new UsernameNotFoundException("User " + username + " has no authorities");
}
UserDetailsAdapter user = new UserDetailsAdapter(account);
return user;
}
The web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml
/WEB-INF/spring/appServlet/security- context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Creates the Filters to handle hibernate lazyload exception -->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
the root-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:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<context:property-placeholder properties-ref="deployProperties"/>
<!-- Remember to correctly locate the right file for properties configuration(example DB connection parameters) -->
<bean id="deployProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"
p:location="/WEB-INF/spring/appServlet/spring.properties" />
<context:annotation-config/>
<context:component-scan base-package="org.treci">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<import resource="/appServlet/data-context.xml"/>
The security context
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<http pattern="/resources" security="none" />
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/" access="permitAll"/>
<intercept-url pattern="/login" access="permitAll"/>
<intercept-url pattern="/login-success" access="hasRole('ROLE_ADMIN')"/>
<form-login login-page="/login"
default-target-url="/login-success"
authentication-failure-url="/login-failed"/>
<logout logout-success-url="/logout"/>
</http>
<beans:bean id="customUserDetailsService" class="org.treci.app.service.CustomUserDetailsService"></beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="customUserDetailsService">
</authentication-provider>
</authentication-manager>
</beans:beans>
I hope some of you can help, save me :)
Here's how I solved the problem:
in the CustomDetailsService I was returning a UserDetails Object by using an Adapter as you can see.
Looking at some tutorial I realized that i should return an org.springframework.security.core.userdetails.User Object.
Here's my new CustomDetailsService implementation:
#Transactional(readOnly=true)
#Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
#Inject AccountDao accountDao;
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
Account account= accountDao.findByUsername(username);
if(account==null) {throw new UsernameNotFoundException("No such user: " + username);
} else if (account.getRoles().isEmpty()) {
throw new UsernameNotFoundException("User " + username + " has no authorities");
}
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
return new User(
account.getUsername(),
account.getPassword().toLowerCase(),
account.isEnabled(),
accountNonExpired,
credentialsNonExpired,
accountNonLocked,
getAuthorities(account.getRoles()));
}
public List<String> getRolesAsList(Set<Role> roles) {
List <String> rolesAsList = new ArrayList<String>();
for(Role role : roles){
rolesAsList.add(role.getName());
}
return rolesAsList;
}
public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (String role : roles) {
authorities.add(new SimpleGrantedAuthority(role));
}
return authorities;
}
public Collection<? extends GrantedAuthority> getAuthorities(Set<Role> roles) {
List<GrantedAuthority> authList = getGrantedAuthorities(getRolesAsList(roles));
return authList;
}
}

Spring + Hibernate + DAO + SessionFactory + Inject

I use Spring with Hibernate and get always a NPE for the sessionFactory Object.
My config file:
#Configuration
public class HibernateConfiguration {
#Bean
public AnnotationSessionFactoryBean sessionFactory() {
Properties props = new Properties();
props.put("hibernate.dialect", MySQL5InnoDBDialect.class.getName());
props.put("hibernate.format_sql", "true");
props.put("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
props.put("hibernate.connection.password", "xxx");
props.put("hibernate.connection.url", "jdbc:mysql://localhost/Market");
props.put("hibernate.connection.username", "philipp");
AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean();
bean.setAnnotatedClasses(new Class[] { xxx.class, xxx.class, xxx.class });
bean.setHibernateProperties(props);
bean.setSchemaUpdate(true);
return bean;
}
#Bean
public HibernateTransactionManager transactionManager() {
return new HibernateTransactionManager(sessionFactory().getObject());
}
#Bean
public PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
My DAOImpl class:
#Repository("xxx")
public class xxxDAOImpl implements xxxDAO {
private SessionFactory sessionFactory;
#Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private Session currentSession() {
return sessionFactory.getCurrentSession();
}
...
Testcase:
#ContextConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
public class TestxxxDAOImpl {
#Test
#Transactional
public void testInsertxxx() throws Exception {
xxxDAO xxxDAO = new xxxDAOImpl();
xyz xyz = new xyz();
xxxDAO.insert(xyz);
assertNotNull(xyz.getId());
}
}
app-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" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="xxx.config" />
<context:component-scan base-package="xxx.dao" />
<context:annotation-config></context:annotation-config>
test-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:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<import resource="classpath:/META-INF/spring/app-context.xml" />
I get always an NPE from the currentSession when the test calls the insert method.
public void insert(xxx xxx) {
currentSession().save(xxx);
}
private Session currentSession() {
return sessionFactory.getCurrentSession();
}
The very first thing to understand when working with Spring is that Spring dependency injection only works for beans obtained from the application context, not for beans created with new.
In Spring-enabled unit tests you configure application context using #ContextConfiguration, for example, as follows (works in Spring 3.1, in previous versions #ContextConfiguration doesn't take #Configuration classes directly, therefore you'll have to create XML configuration file):
#Configuration
public class HibernateConfiguration {
// Add your DAO to application context
#Bean
public xxxDAO xxxDAO() {
return new xxxDAOImpl();
}
...
}
// Configure application context using the given #Configuration class
#ContextConfiguration(classes = HibernateConfiguration.class)
#RunWith(SpringJUnit4ClassRunner.class)
public class TestxxxDAOImpl {
// Obtain DAO from the application context
#Autowired xxxDao xxxDao;
...
}
Instead of sessionFactory.getCurrentSession() in currentSession() function of xxxDAOImpl class, use sessionFactory.openSession().
Since in your first call there would not be any current session in the session factory so you need to open the session.
Hope this helps you. Cheers.

Resources