PDA

View Full Version : NullPointerException using getHibernateTemplate()



RAVEN-I
Oct 30th, 2007, 04:40 AM
Hi Folks,

I find problem using HibernateDaoSupport when I try to get user information from database. My original design was getting ldap authentication through acegi security api and getting user role from my own database.

What I did was extending the LdapAuthenticationProvider and overriding the createUserDetails function inside.

My problem is that while executing the getHibernateTemplate(), a NullPointerException is triggered.

Here is my java class:


public class MyLdapAuthenticationProvider extends LdapAuthenticationProvider {
...
protected UserDetails createUserDetails(LdapUserDetails ldapUser, String username, String password) {
UserDetails userDetails = super.createUserDetails(ldapUser, username, password);
return new AppUserDetailsLdapImpl((LdapUserDetails) userDetails);
}
}


And the Hibernate implementation class is:


public class AppUserDetailsLdapImpl extends HibernateDaoSupport implements LdapUserDetails
{
private final LdapUserDetails ldapUserDetails;
private List userRoleList;


public AppUserDetailsLdapImpl(final LdapUserDetails ldapUserDetails)
{
this.ldapUserDetails = ldapUserDetails;
Attributes attributes = this.ldapUserDetails.getAttributes();
String userName = this.ldapUserDetails.getUsername();
LdapUserDetailsImpl.Essence user = new LdapUserDetailsImpl.Essence(ldapUserDetails);

ArrayList tempGrantedAuthorities = new ArrayList();
userRoleList = getUserRoleList(userName);
Iterator it = userRoleList.iterator();
while (it.hasNext())
{
UserRole userRole = (UserRole)it.next();
GrantedAuthority temp = new GrantedAuthorityImpl(userRole.getRoleID());
tempGrantedAuthorities.add(temp);
}
GrantedAuthority[] extraAuthorities = new GrantedAuthority[tempGrantedAuthorities.size()];
tempGrantedAuthorities.toArray(extraAuthorities);
for (int i = 0; i < extraAuthorities.length; i++) {
user.addAuthority(extraAuthorities[i]);
}
}

public List getUserRoleList(String userID) throws DataAccessException
{
logger.debug("getUserRoleList: " + userID);
return getHibernateTemplate().findByNamedQueryAndNamedPar am("getRolesAuthenticated", "user_id", userID);
}
...


I tried injecting the sessionFactory like the following but another error "No constructor with 0 arguments defined in class 'com.xyz.AppUserDetailsLdapImpl'" comes out:


<bean id="appUserDetailsLdapImpl" class="com.fimat.security.util.AppUserDetailsLdapImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>


Grateful if somebody could beam a light on this issue. Thanks!

Marten Deinum
Oct 30th, 2007, 05:05 AM
You are creating a new one yourself, you don't use the one configured by Spring.



return new AppUserDetailsLdapImpl((LdapUserDetails) userDetails);


Here you are creating a new one outside the Spring container, so nothing gets injected...

RAVEN-I
Oct 30th, 2007, 05:20 AM
Hi mdeinum,

Do you have any suggestion?
As I have already extended the LdapAuthenticationProvider in my class, how can I extend the HibernateDaoSupport?

Or is there any better way to get the data other than the HibernateDaoSupport?

Thx!

RAVEN-I
Oct 30th, 2007, 05:42 AM
I tried to add the HibernateTemplate but cannot solve th NullPointerException issue:


private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public List getUserRoleList(String userID) {
return hibernateTemplate.findByNamedQueryAndNamedParam("getRolesAuthenticated", "user_id", userID);
}


And here is the error:


[#|2007-10-30T18:34:17.854+0800|INFO|sun-appserver-pe9.0|javax.enterprise.system.stream.out|_ThreadID =14;_ThreadName=httpWorkerThread-8080-1;|2007-10-30 18:34:17,854 DEBUG [org.acegisecurity.context.HttpSessionContextIntegr ationFilter] - <SecurityContextHolder now cleared, as request processing completed>
|#]

[#|2007-10-30T18:34:17.854+0800|SEVERE|sun-appserver-pe9.0|javax.enterprise.system.container.web|_Threa dID=14;_ThreadName=httpWorkerThread-8080-1;_RequestID=9e7e089c-71a1-461c-be9b-2a9e857e6990;|StandardWrapperValve[default]: Servlet.service() for servlet default threw exception
java.lang.NullPointerException
at com.fimat.security.util.LdapRoleAuthenticationProv ider.createUserDetails(LdapRoleAuthenticationProvi der.java:36)
at org.acegisecurity.providers.ldap.LdapAuthenticatio nProvider.retrieveUser(LdapAuthenticationProvider. java:235)
at org.acegisecurity.providers.dao.AbstractUserDetail sAuthenticationProvider.authenticate(AbstractUserD etailsAuthenticationProvider.java:119)
at org.acegisecurity.providers.ProviderManager.doAuth entication(ProviderManager.java:195)

Would you suggest way to inject the sessionFactory? if needed?
Because the ldapRoleAuthenticationProvider in config file is already defined the constructor-arg of BindAuthenticator and DefaultLdapAuthoritiesPopulator.

Marten Deinum
Oct 30th, 2007, 05:55 AM
As long as you are creating it yourself and you aren't setting the sessionfactory yourself nothing is going to work.

The instance you create isn't managed by Spring and thus nothing will ever get injected.

RAVEN-I
Nov 5th, 2007, 03:33 AM
In view of the complexity of extending the LdapAuthenticationProvider, for simplicity reason, I finally decideded to call the hibernate function directly. In other parts of the application, I'll reuse the hibernate functions exposed by spring.

karldmoore
Nov 5th, 2007, 11:59 AM
Why can't you simply inject the reference you need instead of creating a new one youself?

RAVEN-I
Nov 6th, 2007, 12:16 AM
I tried to inject the sessionFactory into my own LdapAuthenticationProvider, but I find no place to do that. My LdapAuthenticationProvider is like:



<bean id="ldapRoleAuthenticationProvider" class="com.xyz.security.util.LdapRoleAuthenticationProvid er">
<constructor-arg>
<bean class="org.acegisecurity.providers.ldap.authenticator.Bin dAuthenticator">
<constructor-arg>
<ref local="initialDirContextFactory"/>
</constructor-arg>
<property name="userSearch" ref="userSearch"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.acegisecurity.providers.ldap.populator.Default LdapAuthoritiesPopulator">
<constructor-arg>
<ref local="initialDirContextFactory"/>
</constructor-arg>
<constructor-arg>
<value>OU=Users,OU=My City</value>
</constructor-arg>
<property name="groupRoleAttribute">
<value>cn</value>
</property>
</bean>
</constructor-arg>
</bean>