Archive for the ‘Java’ Category

maven, junit, cobertura and BeanCreationException

Monday, January 11th, 2010

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 my service classes do not have interfaces and I can’t be bothered to go through and add them.

Tomcat Error listenerStart

Monday, July 6th, 2009

I’m sure I’m not the only one who has battled with this startup error:

4985 [main] ERROR org.apache.catalina.core.StandardContext  - Error listenerStart
4985 [main] ERROR org.apache.catalina.core.StandardContext  - Context [/mycontext] startup failed due to previous errors

The problem is getting the real cause of the problem to appear in the log. I’ve had this problem various times in the past (must be repeating the same mistakes). Today’s answer was simple:

  1. Remove log4j.jar from myapp/WEB-INF/lib (it is already in Tomcat/common/lib)
  2. Restart app.
  3. Debug using the reams of useful error messages which suddenly appear in the output.

Spring Security: Method Level Security with JSF so far…

Thursday, April 9th, 2009

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

Thursday, April 9th, 2009

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…

a4j:commandLink action not executed in datatable

Tuesday, February 17th, 2009

I have an <a4j:commandLink> in a <rich:datatable>. The same problem applies to <a4j:commandButton> and <a4j:repeat>. The bean action specified was not executed, and the <a4j:actionparam> values were not bound.

For example this was not working:

<a4j:form>
   <rich:dataTable id="searchResults" value="#{myBean.searchResults}" var="item">
            <rich:column>
               <a4j:commandLink value="#{item.code}" action="#{myBean.myAction}"
                reRender="myRegion">
                    <a4j:actionparam name="code" value="#{item.code}"
                     assignTo="#{myBean.selectedCode}"/>
                </a4j:commandLink>
              </rich:column>
   </rich:dataTable>
</a4j:form>

The region was getting rerendered, but myBean.myAction was not executed.

Then I tried moving the <a4j:form> inside the table, so there was a form on each row:

   <rich:dataTable id="searchResults" value="#{myBean.searchResults}" var="item">
      <rich:column>
              <a4j:form>
               <a4j:commandLink value="#{item.code}" action="#{myBean.myAction}"
                reRender="myRegion">
                    <a4j:actionparam name="code" value="#{item.code}"
                     assignTo="#{myBean.selectedCode}"/>
                </a4j:commandLink>
                </a4j:form>
              </rich:column>
   </rich:dataTable>

This seemed to work for the first row, but not any subsequent ones.

The answer seems to be to base the dataTable on a session scoped bean. I didn’t want my orignal bean session scoped, so I split it into two like this:

 <rich:dataTable id="searchResults" value="#{mySessionBean.searchResults}" var="item">
      <rich:column>
              <a4j:form>
               <a4j:commandLink value="#{item.code}" action="#{myBean.myAction}"
                reRender="myRegion">
                    <a4j:actionparam name="code" value="#{item.code}"
                     assignTo="#{myBean.selectedCode}"/>
                </a4j:commandLink>
                </a4j:form>
              </rich:column>
   </rich:dataTable>

And it works. The actions are still carried out on my request bean as I wanted and I just have to be careful about how I update the session bean.

NoClassDefFoundError com.sun.activation.registries.LogSupport

Monday, February 9th, 2009

I’m trying to run a single Junit test via Eclipse and getting this error. But I don ‘t get the error if I run the whole suite of junit tests using ant. The jars activation.jar and mail.jar are definitely in my Project classpath.

The answer: go to Project > Properties > Java Build Path > Order and Export. Move activation.jar up the list.

JSF - rich:datatable and HashMap

Wednesday, February 4th, 2009

I wanted to display the data from a Map using a rich:datatable. You can do this by using an array of the Map keys as the value for the table, and then using this to access the rest of the data in the Map.

Here is the java:

public Map<Integer,MyObject> getItems() {
   return items;
}
public List<Integer> getItemKeys() {
   List keys = new ArrayList();
   keys.addAll(getItems().keySet());
   return keys;
}

and here is the JSF:

<rich:dataTable value="#{myBean.itemKeys}" var="key" >
   <rich:column>
      <h:outputText value="#{myBean.items[key].myObjProperty}"/>
   </rich:column>
</rich:dataTable>

Obviously somewhat simplified but I think this shows how to do it!

Custom Hibernate Sequence Generator for Id field

Tuesday, January 27th, 2009

I have a table with a primary key in the format M001, M002 etc (lets not think about what happens after M999 for now). I’m using Hibernate Annotations, and I found a great way of generating the Primary Key value for new Records:

First I created a database sequence to use. Then I implemented org.hibernate.id.IdentifierGenerator;

public class StockCodeGenerator implements IdentifierGenerator {

    private static Logger log = Logger.getLogger(StockCodeGenerator.class);

    public Serializable generate(SessionImplementor session, Object object)
            throws HibernateException {

        String prefix = "M";
        Connection connection = session.connection();
        try {

            PreparedStatement ps = connection
                    .prepareStatement("SELECT nextval ('seq_stock_code') as nextval");

            ResultSet rs = ps.executeQuery();
            if (rs.next()) {
                int id = rs.getInt("nextval");
                String code = prefix + StringUtils.leftPad("" + id,3, '0');
                log.debug("Generated Stock Code: " + code);
                return code;
            }

        } catch (SQLException e) {
            log.error(e);
            throw new HibernateException(
                    "Unable to generate Stock Code Sequence");
        }
        return null;
    }
}

Then, in my entity class, I simply annotate the id field like this:

@Id
@GenericGenerator(name="seq_id", strategy="my.package.StockCodeGenerator")
@GeneratedValue(generator="seq_id")
@Column(name = "stock_code", unique = true, nullable = false, length = 20)
public String getStockCode() {
    return this.stockCode;
}

It works really well!

[Thanks to Jejomar Dimayuga for this post http://blog.dagitab.com/htsrv/trackback.php?tb_id=30 which I have modified slightly to use a sequence rather than a table]

dbunit, Postgres and NoSuchTableException

Tuesday, December 16th, 2008

I am having trouble running some dbunit tests against Postgres.

I’ve managed to extract some data from the database into an XML file with no trouble at all, using the following code:

IDatabaseConnection connection = new DatabaseConnection( conn );
QueryDataSet partialDataSet = new QueryDataSet(connection);
partialDataSet.addTable("mytable", " SELECT * FROM mytable WHERE id=1068 ");
FlatXmlWriter datasetWriter = new FlatXmlWriter(new FileOutputStream("mydata.xml"));
datasetWriter.write( partialDataSet );

But then I can’t reload it using the following code:

DatabaseOperation.INSERT.execute(connection, new FlatXmlDataSet(
					this.getClass().getClassLoader().getResourceAsStream(
							"mydata.xml")));

The error I get is a variation on org.dbunit.dataset.NoSuchTableException: mytable.

I’ve tried specifiing the schema when I create the connection, I’ve tried editing the xml to include the schema. I thought it was a problem with case, as sometimes the error message shows the table name in uppercase depending on what I have fiddled with, but it seems to make no difference. The table is definitely there as I extracted data from it fine. Argh what a nuisance.

AbstractTransactionalDataSourceSpringContextTests and auto-wire

Monday, November 24th, 2008

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!