a4j:commandLink action not executed in datatable

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

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

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 :(