maven, junit, cobertura and BeanCreationException

I have a set of junit tests for my project. When I run them with mvn test they run fine and pass.

However, when I ran them with mvn cobertura:cobertura, they failed with the following error:

org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'com.anorakgirl.MyTest': Autowiring of fields failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private com.anorakgirl.MyService com.anorakgirl.MyTest.myService;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [com.anorakgirl.MyService] is defined:
Unsatisfied dependency of type [class com.anorakgirl.MyService]:
expected at least 1 matching bean

After some googling, this is the problem. The ServiceObject was annotated with @Autowire. Spring autowires by type. I have only one class of type ‘com.anorakgirl.MyService’. So when run with junit this works fine. However, cobertura changes the type of the MyService class during Instrumentation, so Spring no longer recognises it as type MyService, and so cannot Autowire.

There are two possible answers:

The easy answer (what I did)

In your test application context add the line:

<aop:config proxy-target-class="true"/>

The other answer (what I read about)

Make sure the classes that you want to autowire all implement interfaces. Then autowire the interface rather than the implementation. The Cobertura class will still implement the same interface and therefore can still be autowired.

I didn’t try this as the service classes do not have interfaces and I haven’t time to add them!

Spring Security: Method Level Security with JSF so far…

My personal Gotcha’s in case they are of use to anyone else:

1. Ensure you have compatible versions of Spring and Spring Security. I am using Sping Security 2.0.4 and Spring 2.5.6. Originally my Spring was a slightly older version (2.5) and I got the following error:

java.lang.NoSuchMethodError:
org.springframework.aop.config.AopNamespaceUtils.registerAutoProxyCreatorIfNecessary

I fixed this by upgrading to the latest Spring. I think the problem was resolved in Spring 2.5.2 and relates to this bug: http://jira.springframework.org/browse/SPR-4459

2. Make sure the methods you are securing are actually in Spring Managed beans, doh! My @Secured annoration was being ignored entirely, and it took me ages to realise why – some of my beans are still in faces config files, so Spring has no way of knowing about them. Moving the beans into the Spring configuration fixed the problem straight away.

Spring Security 2.0: NTLM filter with custom UserDetailsService

I used this blog to get started: http://blog.mediasoft.be/ntlm-with-spring-security-20/

My Application-context is pretty much as per the Spring 2.0 configuration at the bottom of the post, with the following changes:

  • Different properties for the ntlm filter
  • servlet-api-provision=”false” on the <security:http> tag
  • Addition of custom UserDetailsService.

The full config is below:

<security:authentication-manager alias="_authenticationManager" />

    <bean id="authenticationProvider"
     class="com.mydomain.security.UserDetailsAuthenticationProvider">
        <security:custom-authentication-provider />
        <property name="userDetailsService" ref="userDetailsService" />
    </bean>

    <bean id="userDetailsService" class="com.mydomain.security.UserDetailsServiceImpl">
        <property name="daoUser" ref="daoUser" />
    </bean>

    <bean id="ntlmFilter" class="org.springframework.security.ui.ntlm.NtlmProcessingFilter">
        <security:custom-filter position="NTLM_FILTER" />
        <property name="stripDomain" value="true" />
        <property name="defaultDomain" value="mydomain.com" />
        <property name="domainController" value="mycontroller" />
        <property name="authenticationManager" ref="_authenticationManager" />
    </bean>

    <bean id="ntlmEntryPoint"
     class="org.springframework.security.ui.ntlm.NtlmProcessingFilterEntryPoint">
        <property name="authenticationFailureUrl" value="/denied.xhtml" />
    </bean>

    <bean id="exceptionTranslationFilter"
     class="org.springframework.security.ui.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint" ref="ntlmEntryPoint" />
    </bean>

    <security:http access-denied-page="/denied.xhtml"
     entry-point-ref="ntlmEntryPoint" servlet-api-provision="false">
        <security:intercept-url pattern="/denied.xhtml" filters="none" />
        <security:intercept-url pattern="/**" access="ROLE_USER" />
    </security:http>

My UserDetailsAuthenticationProvider is exactly as per the blog.

My UserDetails Service is below. Note that the UserDetails created should have blank password. This confused me for a bit.

public class UserDetailsServiceImpl implements UserDetailsService {
	private UserDAO daoUser;
	private static Logger log = Logger.getLogger(UserDetailsService.class);

	public UserDAO getDaoUser() {
		return daoUser;
	}

	public void setDaoUser(UserDAO daoUser) {
		this.daoUser = daoUser;
	}

	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {

		MyUser user;

		try {
			user = daoUser.getUser(username);
		} catch (DAOException ex) {
			throw new DataRetrievalFailureException(ex.getMessage());
		}

        if (user != null) {

            ArrayList<GrantedAuthority> ga = new ArrayList<GrantedAuthority>();
            ga.add(new GrantedAuthorityImpl("ROLE_USER"));
            GrantedAuthority[] grantedAuthorities = new GrantedAuthority[ga.size()];
            ga.toArray(grantedAuthorities);

            UserDetailsImpl ud = new UserDetailsImpl(username, "", true, grantedAuthorities, user);
            return ud;
        } else {
            throw new UsernameNotFoundException("Username Not Found");
	}
}

My UserDetailsImpl simply extends org.springframework.security.userdetails.User and has an additional field for my ‘MyUser’

public class UserDetailsImpl extends org.springframework.security.userdetails.User {

	private static final long serialVersionUID = 1584153957347843760L;

	private MyUser user;

	public UserDetailsImpl(String username, String password, boolean enabled,
			 GrantedAuthority[] authorities, MyUser user)
			throws IllegalArgumentException {
		super(username, password, enabled, true, true,
				true, authorities);
		this.user = user;
	}

	public MyUser getUser() {
		return user;
	}

	public void setUser(MyUser user) {
		this.user = user;
	}
}

And that seems to work. Now I am trying to enable method level security, so more to come soon…

AbstractTransactionalDataSourceSpringContextTests and auto-wire

I got stuck last week because we have two DataSource beans with different names, for different databases. My AbstractTransactionalDataSourceSpringContextTests Unit Tests did not like this:

Unsatisfied dependency expressed through bean property 'dataSource':
No unique bean of type [javax.sql.DataSource] is defined:
expected single matching bean but found 2

The problem is that by default AbstractTransactionalDataSourceSpringContextTests is set to autowire by type. I changed this to autowire by name, in the getConfigLocations method:

protected String[] getConfigLocations(){
        setAutowireMode(AUTOWIRE_BY_NAME);
        return new String[]{ "test-applicationContext.xml" };
    }

To get the Daos I was testing injected, all I had to do was create getters and setters with the same names as I had specified for for the Dao beans in my applicationContext. So little to do!

Spring web mvc and url mapping

Back to an old problem that I haven’t resolved. I want to map everything to my Spring Controller. So I can have urls like mydomain.com/this and mydomain.com/that

So I put this in my web.xml

<servlet-mapping>
	<servlet-name>myservlet</servlet-name>
	<url-pattern>/*</url-pattern>
</servlet-mapping>

I’m using the Spring Dispatcher Servlet, with jsp as the view, using
org.springframework.web.servlet.view.InternalResourceViewResolver in my spring config.  But it can’t find the view. I get:

NOT_FOUND RequestURI=/webapp/WEB-INF/jsp/main.jsp

In the logs is:
WARN org.springframework.web.servlet.PageNotFound
– No mapping found for HTTP request with URI [/webapp/WEB-INF/jsp/main.jsp] in
DispatcherServlet with name ‘myservlet’

So the request for the view is going through the Dispatcher Servlet too. Not sure how to get around this! This blog is turning into a list of problems, rather than solutions…