How can I customize the CMP Field mapping in EAP6

Solution Verified - Updated -

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP)
    • 6.x

Issue

  • How can I customize JDBC statements for EJB (CMP) Entity fields
  • There is a class not found Exception if I migrate the CMP mapper from EAP5 to EAP6

Resolution

To customize the mapping you need to implement the interfaces JDBCParameterSetter JDBCResultSetReader and adjust the application configuration.

create a mapping for the jbosscmp-jdbc.xml in your application

<jbosscmp-jdbc>
  <defaults>
    <datasource>java:jboss/datasources/yourDSname</datasource>
    <!-- with EAP6 you need to set the mapping inside the application defaults -->
    <datasource-mapping>Oracle9i_withTimestampMapping</datasource-mapping>
  </defaults>
  ...
  <type-mappings>
    <name>Oracle9i_withTimestampMapping</name>
    ...    
    <mapping>
      <java-type>java.sql.Timestamp</java-type>
      <jdbc-type>TIMESTAMP</jdbc-type>
      <sql-type>TIMESTAMP(3) WITH TIME ZONE</sql-type>
      <param-setter>org.jboss.cmp.OracleTimestampMapper</param-setter>
      <result-reader>org.jboss.cmp.OracleTimestampMapper</result-reader>
    </mapping>
  </type-mappings>

A template for the mapping can be taken from the standardjbosscmp-jdbc.xml which is in the configuration folder of EAP4/EAP5 or within the org/jboss/as/cmp module archive.

Create the mapper class

This example store the date in an Oracle column with the current Timezone

public final class OracleTimestampMapper implements JDBCParameterSetter, JDBCResultSetReader {
  public void set(PreparedStatement ps, int index, int jdbcType, Object value, Logger log) throws SQLException {
    // get the underlying Oracle Statement
    WrappedPreparedStatement wps = (WrappedPreparedStatement) ps;
    OraclePreparedStatement ops = (OraclePreparedStatement) wps.getUnderlyingStatement();

    if (value == null) {
      ops.setNull(index, jdbcType);
    } else {
      // store Oracle specific Timestamp into the TIMESTAMP WITH TIMEZONE column
      TIMESTAMPTZ ts;
      java.sql.Timestamp dt = (java.sql.Timestamp) value;
      ts = new TIMESTAMPTZ(ops.getConnection(), dt, Calendar.getInstance());
      ops.setTIMESTAMPTZ(index, ts);
    }
  }

  public Object get(ResultSet rs, int index, Class destination, Logger log) throws SQLException {
    return rs.getTimestamp(index);
  }

Root Cause

The Mapper interface is moved to a different package. From org.jboss.ejb.plugins.cmp.jdbc to org.jboss.as.cmp.jdbc.

There is an issue with classloading and it is necessary to add the custom module to the cmp subsystem as dependency. BZ924548
From 6.3.2 on this is not longer necessary as the class will be loaded from the applications classloader.

Related articles
Field mapping for custom classes in EAP6

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Comments