JSF – rich:datatable and HashMap

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

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

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

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!

  

jasper reports – parameters for ‘in clause’

I found a really useful function today, allowing you to supply a List as a parameter, and use in your SQL Query  with IN or NOT IN.

Supply the parameter as a List:

<parameter name="myList" isForPrompting="true" class="java.util.List"/>

Then use the the function

$X{IN, <column>, <param>}

For example

<queryString><![CDATA[SELECT *
FROM mytable WHERE $X{IN, mycolumn,myList}]]>
</queryString>

Very useful!

  

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…

  

optional parameters in Jasper reports

I have been mainly writing Jasper reports this week. There seems to be a dearth of documentation (unless you pay for ‘The Definitive Guide’), but a combination of iReport and trial and error seems to be working.

I wanted to reuse the same report with some optional parameters – add an additional condition to the where clause if a certain paramteter was supplied. I realise that I can pass an entire SQL statement into the report, or even some objects containing the data, but I like the consistency of having valid SQL in the report and letting Jasper substitute the parameters appropriately.

My solution was to use the ‘case’ statement (I’m using PostgreSQL):

WHERE manager = (case when $P{manager} != '' then $P{manager} else manager end)

I guess there would be performance implications on a big dataset, but it seems to work.

  

java.lang.NoSuchMethodError: javax.servlet.ServletResponse.getContentType()

On windows XP when I start Tomcat 5.5.27 throught the eclipse plugin, and try to view a JSF app in a browser. When I start Tomcat at the command line it seems to be fine, but then I can’t use the Eclipse debugging features etc.

I guess Eclipse is including some innappropriate jar files in the classpath or something, but I’ve no idea where to look :(

  

Agilefant?

After all that fiddling with xplanner, we decided to use Agilefant (The Finnish Ferrari for backlog management!) instead. It requires JDK 1.6, Tomcat 5.5 and MySQL. I think it would work with PosgreSQL, but no database script was provided. It worked straight away (all we had to do was create the database and put the war file into the webapps directory) and seems to be under current development, which is 2 up on xplanner already! It seems quite new and I’m not sure that it has been widely adopted, so we’ll see how we get on.

  

Getting Xplanner working

Xplanner is a project planning and tracking tool for agile development teams, which we’ve been recommended to use at work. The only problem is, no-one seems to have done any work on it since 2006, and it only officially works in jdk 1.4, and some old version of Tomcat. Our server runs PostgreSQL 8, Tomcat 5.5 and jdk 1.6. One of the main problems we had was that the automatic migration process did not seem to work for Postgres. This is what I did to get it to work:

  1. Downloaded version 0.7b4. Amended xplanner-custom.properties to point to the postgres database. Used ant to install the database.
  2. Downloaded version 0.7b7. Followed installation instructions.
  3. Patched the database myself. The scripts are in  WEB-INF\classes\patches. I had to amend them to work with Postgres (e.g. datetime -> timestamp, tinyint -> boolean). I only had to run the later ones.
  4. Deleted the patch scripts
  5. Deleted the file \WEB-INF\classes\com\technoetic\xplanner\upgrade\CleanUpNoteTableConstraints.class as it didn’t seem to like this either.
  6. Followed these instructions: http://espritlibre.org/2008/07/10/xplanner-spring-and-jdk-16/

And after all that, it seems to work, phew!