2 Replies Latest reply on Nov 30, 2005 11:36 AM by ansancle

    Using user-type-mappings for Enums

    ansancle

      Im using JBoss 4.0.2, Eclipse 3.1.0, JBoss-IDE 1.5.0.RC1, MySQL 4.1.12, mysql-connector-java-3.1.7-bin.jar on Red Hat Enterprise 3 Linux.

      I have an entity bean with 2 enumerated types that I want to store in the database as integers. I have followed the instructions in the WIki ; http://wiki.jboss.org/wiki/Wiki.jsp?page=UserTypeMapping
      1. Created mapping classes that implement the Mapper interface
      2. Added the following to the jbosscmp-jdbc.xml file :

      <user-type-mappings>
       <user-type-mapping>
       <java-type>com.digitalhome.msg.DHActionType</java-type>
       <mapped-type>java.lang.Integer</mapped-type>
       <mapper>com.digitalhome.db.DHActionTypeMapper</mapper>
       </user-type-mapping>
       <user-type-mapping>
       <java-type>com.digitalhome.msg.DHMessageType</java-type>
       <mapped-type>java.lang.Integer</mapped-type>
       <mapper>com.digitalhome.db.DHMessageTypeMapper</mapper>
       </user-type-mapping>
      </user-type-mappings>
      
      


      Here is the code for one of the mapper classes :
      /**
       * DigitalHome copyright 2005
       *
       * Filename : DHActionTypeMapper.java
       * Package : com.digitalhome.db
       * Create Date : Nov 18, 2005
       * Author : root
       *
       */
      package com.digitalhome.db;
      
      import org.jboss.ejb.plugins.cmp.jdbc.Mapper;
      
      import com.digitalhome.msg.DHActionType;
      
      /**
       * @author root
       *
       */
      public class DHActionTypeMapper implements Mapper
      {
      
       /**
       * Constructor
       */
       public DHActionTypeMapper()
       {
       super();
       // TODO Auto-generated constructor stub
       }
      
      
       /**
       * This method is called when CMP field is stored.
       * @param fieldValue - CMP field value
       * @return column value.
       */
       public Object toColumnValue(Object fieldValue)
       {
       DHActionType type = (DHActionType)fieldValue;
       return new Integer(type.getType());
       }
      
       /**
       * This method is called when CMP field is loaded.
       * @param columnValue - loaded column value.
       * @return CMP field value.
       */
       public Object toFieldValue(Object columnValue)
       {
       int ordinal = ((Integer)columnValue).intValue();
       return DHActionType.getActionType(ordinal);
       }
      
      }





      I have breakpoints set in the mapper classes which are never hit, so it appears the mapper classes are not being called, and the values in the database for the enum columns are not being entered properly, the default of 0 is being entered.

      Does anyone have any ideas on what Im doing wrong or missing?
      Thanks
      -Andy





        • 1. Re: Using user-type-mappings for Enums
          ansancle

          I figured this out and am posting this for anyone else who is having a problem with enums in entitybeans using jboss.

          This won't work if you are not using java 5.0

          To have an entitybean with an enum as a cmp field create an enum in the following manner :

          public enum DHMessageType
          {
           INFO, ALARM, WARNING, ERROR, STATUS, DEBUG
          }
          


          At this point you can add this class into your EntityBean as a CMP field and it will work properly, however it will be stored as a blob. This means you will not be able to see the value in the database, or search/sort off the value.

          If you want to store the value as a String, do the following :
          1. Create a mapping class, this class will be called when the enum is being stored to the db or read from the db.
          Here is what the class should look like :

          package com.foo.dbtest;
          import org.jboss.ejb.plugins.cmp.jdbc.Mapper;
          
          public class DHActionTypeMapper implements Mapper
          {
           public DHActionTypeMapper()
           {
           super();
           }
          
           public Object toColumnValue(Object fieldValue)
           {
           return ((DHActionType)fieldValue).toString();
           }
          
           public Object toFieldValue(Object columnValue)
           {
           String strValue = ((String)columnValue).toString();
           return DHActionType.valueOf(strValue);
           }
          }
          


          The next step is to add the following into the jbosscmp-jdbc.xml file after the </enterprise-bean> section

          <user-type-mappings>
          
           <user-type-mapping>
           <java-type>com.digitalhome.msg.DHActionType</java-type> NOTE -> The type that needs to be mapped
           <mapped-type>java.lang.String</mapped-type> -> The java type to map to for storing
           <mapper>com.digitalhome.msg.DHActionTypeMapper</mapper> -> The class that will handle the mapping
           </user-type-mapping>
          </user-type-mappings>


          ** WARNING - If you are using Eclipse and JbossIDE when you regenerate your xdoclet this section will get erased in jbosscmp-jdbc.xml. I still haven't figured out where the merge point for this is so I can take it out of this file and not have this happen, if anyone knows feel free to reply.

          Hope this helps someone.



          • 2. Re: Using user-type-mappings for Enums
            ansancle

            Another update and answer to my own question. If you are using Eclipse and the JBossIDE and want to have the user-type-mappings added into jbosscmp-jdbc.xml via a merge file so it doesn't get overwritten during regeneration, do the following.

            1. Open your XDoclet configuration and select your EJB configuration. Select the ejbdoclet and then select the jboss item. Find the mergedir property and select it, add in a directory that you want to use for the merge directory as this properties value.

            Click Apply.

            Create a file called jbosscmp-jdbc-typemappings.xml in the directory you specified as the mergedir, open this file and add in the mapping code :

            <user-type-mappings>
             <user-type-mapping>
             <java-type>com.digitalhome.msg.DHActionType</java-type>
             <mapped-type>java.lang.String</mapped-type>
             <mapper>com.digitalhome.msg.DHActionTypeMapper</mapper>
             </user-type-mapping>
            </user-type-mappings>


            Save this file and Run XDoclet, this code will be inserted in the proper place inside of jbosscmp-jdbc.xml