Re: Cayenne 3.0M4 ignoring extended data types

From: Chris Gamache (cgamach..mail.com)
Date: Fri Aug 01 2008 - 15:17:49 EDT

  • Next message: Andrus Adamchik: "Re: Cayenne 3.0M4 ignoring extended data types"

    Here's the code for my extended type which works fine in 2.0, and for data
    objects of type uniqueidentifier obtained from a first generation query, and
    not from a relational fetcher.

    public class PostgresUniqueIdentifier implements ExtendedType {
     public String getClassName() {
      return "java.util.UUID";
     }
     public Object materializeObject(CallableStatement rs, int index, int type)
       throws Exception {
      if (type == Types.NULL) {
       return null;
      } else {
       return UUID.fromString(rs.getString(index));
      }

     }
     public Object materializeObject(ResultSet rs, int index, int type) throws
    Exception {
      if (type == Types.NULL) {
       return null;
      } else {
       if(rs.getString(index) != null){
        return UUID.fromString(rs.getString(index));
       }else{
        return(null);
       }
      }
     }
     public void setJdbcObject(PreparedStatement statement, Object value,
       int pos, int type, int precision) throws Exception {
      if (value == null) {
       statement.setNull(pos, Types.NULL);
      } else if (value instanceof UUID) {
       statement.setObject(pos,((UUID)value).toString());
      } else if (value instanceof String) {
       statement.setObject(pos,(String)value);
      }

     }

        public boolean validateProperty(
                Object source,
                String property,
                Object value,
                DbAttribute dbAttribute,
                ValidationResult validationResult) {
         String message = "";

         if (value == null) {
          return true;
         }

            if (value instanceof UUID) {
             return true;
            } else if (value instanceof String) {
          try {
           UUID uuid = UUID.fromString((String)value);
           return true;
          } catch (Exception e) {
                    message = "\""
                        + property
                        + "\" does not match UUID format";
                    return false;
          }
            } else {
             message = "\""
                    + property
                    + "\" is not a UUID";
            }
            validationResult.addFailure(new BeanValidationFailure(
                    source,
                    property,
                    message));

            return false;
        }

    }
    I still contentend that the behavior I'm experiencing is buggy behavior on
    Cayenne 3.0's part.

    On Fri, Aug 1, 2008 at 1:43 PM, Michael Gentry <blacknex..mail.com> wrote:

    > My best guess at the moment is you are not registering it in your
    > DataNode or you have a class path issue or you haven't implemented an
    > ExtendedType for Cayenne to know how to deal with it. Actually,
    > java.util.UUID is not a Cayenne ExtendedType and you probably need a
    > wrapper around it for Cayenne to be able to read/write the type and
    > work with the data.
    >
    > Take a look at:
    >
    >
    > http://cayenne.apache.org/doc/api/org/apache/cayenne/access/types/ExtendedType.html
    >
    >
    > On Fri, Aug 1, 2008 at 1:29 PM, Chris Gamache <cgamach..mail.com> wrote:
    > > I've been looking around, stepping through the code execution, trying to
    > > find where Cayenne goes digging into the ExtendedTypeMap, and to see if
    > that
    > > step gets omitted when dealing with referenced tables. I'm still looking,
    > > but I did find one odd thing so far:
    > >
    > > In org.apache.cayenne.access.jdbc.ColumnDescriptor, the javaClass for the
    > > column with the extended type is null. It should most definitely be
    > > java.util.UUID as evidenced by the entry in the XML file. No other column
    > > (at least none that I've looked at) has a null for the javaClass. Is this
    > > normal, or a symptom of the type of problem that exists?
    > > On Thu, Jul 31, 2008 at 11:55 PM, Chris Gamache <cgamach..mail.com>
    > wrote:
    > >
    > >> Every time I create a DataContext, it gets created with makeContext. I
    > >> pass in different the config locations.
    > >>
    > >> I didn't post the code for PostgresUniqueidentifier or PostgresMoney
    > >> because I didn't think the guts of those classes really mattered, but
    > >> more that they existed in the first place. PostgresUniqueidentifier
    > >> will take a java.util.UUID and allow it to be treated as a JDBC string
    > >> with no explicit typecasting when using PostgreSQL. PostgresMoney
    > >> wraps itself aroung the PGmoney class from the PgJDBC library and
    > >> allows seamless access to that datatype. I don't set them up in the
    > >> XML. Should I? Is there a 3.0 feature I'm missing? I'll be glad to
    > >> post those classes if you'd like to see them. It's just a whole lot
    > >> for a listserv. Just say the word...
    > >>
    > >> They themselves function properly (at least in 2.0 they did) ...
    > >>
    > >> On 7/31/08, Michael Gentry <blacknex..mail.com> wrote:
    > >> > It is a lot to dig through ... :-)
    > >> >
    > >> > Some more questions:
    > >> >
    > >> > You show regsitering PostgresUniqueIdentifier and PostgresMoney in the
    > >> > code, but they are not in the XML. Is this a red herring or an
    > >> > omission? Do you have the full class name, including package name, in
    > >> > the XML for your types?
    > >> >
    > >> > Also, are you registering your ExtendedTypes in ALL DataNodes? You
    > >> > mentioned having having multiple cayenne.xml files and the
    > >> > ExtendedTypes need to be registered in ALL DataNodes because each
    > >> > DataNode is responsible for doing type translation processing.
    > >> >
    > >> > And, do your ExtendedTypes implement ExtendedType? Or subclass
    > >> > something which does?
    > >> >
    > >> > Thanks.
    > >> >
    > >> >
    > >> > On Thu, Jul 31, 2008 at 1:13 PM, Chris Gamache <cgamach..mail.com>
    > >> wrote:
    > >> >> On Thu, Jul 31, 2008 at 12:38 PM, Michael Gentry
    > >> >> <blacknex..mail.com>wrote:
    > >> >>
    > >> >>> Could you give an example of how you are using and declaring the
    > >> >>> extended types? A lot of work has been done in that department
    > since
    > >> >>> 2.x, including adding enumeration support.
    > >> >>
    > >> >>
    > >> >> Sure!
    > >> >>
    > >> >> public DataContext makeContext(final String configuration, final
    > String
    > >> >> classPath, final String nodeName ) {
    > >> >>
    > >> >> if (!initialized) {
    > >> >> DefaultConfiguration dc = new DefaultConfiguration(configuration);
    > >> >> dc.addClassPath(classPath);
    > >> >> boolean cayenneNotInitialized = false;
    > >> >> try {
    > >> >> Configuration conf = Configuration.getSharedConfiguration();
    > >> >> } catch (Exception e) {
    > >> >> cayenneNotInitialized = true;
    > >> >> }
    > >> >>
    > >> >> if (cayenneNotInitialized) {
    > >> >> dc.initializeSharedConfiguration(dc);
    > >> >> } else {
    > >> >> try{
    > >> >> dc.initialize();
    > >> >> }catch(Exception e){
    > >> >> throw new ConfigurationException();
    > >> >> }
    > >> >> }
    > >> >>
    > >> >> for (Object d : dc.getDomain().getDataMaps().toArray()) {
    > >> >> DataMap dm = (DataMap)d;
    > >> >> }
    > >> >> for (Object d : dc.getDomain().getDataNodes().toArray()) {
    > >> >> DataNode dn = (DataNode)d;
    > >> >> }
    > >> >> * //Heres where I'm registering the types...*
    > >> >>
    > >> >>
    > >> >>
    > >>
    > dc.getDomain().getNode(nodeName).getAdapter().getExtendedTypes().registerType(new
    > >> >> PostgresUniqueIdentifier());
    > >> >>
    > >> >>
    > >>
    > dc.getDomain().getNode(nodeName).getAdapter().getExtendedTypes().registerType(new
    > >> >> PostgresMoney());
    > >> >> Configuration sharedConfig = null;
    > >> >> try {
    > >> >> sharedConfig = Configuration.getSharedConfiguration();
    > >> >> Iterator<DataMap> dcDataMapItr =
    > >> >> dc.getDomain().getDataMaps().iterator();
    > >> >> while (dcDataMapItr.hasNext()) {
    > >> >> sharedConfig.getDomain().addMap(dcDataMapItr.next());
    > >> >> }
    > >> >> Iterator<DataNode> dcDataNodeItr =
    > >> >> dc.getDomain().getDataNodes().iterator();
    > >> >> while(dcDataNodeItr.hasNext()) {
    > >> >> sharedConfig.getDomain().addNode(dcDataNodeItr.next());
    > >> >> }
    > >> >> } catch (Exception e) {
    > >> >> Configuration.initializeSharedConfiguration(dc);
    > >> >> }
    > >> >>
    > >> >> initialized = true;
    > >> >> }
    > >> >> for (Object d :
    > >> >>
    > >>
    > Configuration.getSharedConfiguration().getDomain().getDataMaps().toArray())
    > >> >> {
    > >> >> DataMap dm = (DataMap)d;
    > >> >> }
    > >> >> for (Object d :
    > >> >>
    > >>
    > Configuration.getSharedConfiguration().getDomain().getDataNodes().toArray())
    > >> >> {
    > >> >> DataNode dn = (DataNode)d;
    > >> >> }
    > >> >>
    > >> >> return DataContext.createDataContext();
    > >> >> }
    > >> >>
    > >> >> And here's some XML for declaring the fields...
    > >> >> <obj-entity name="CompanyTable"
    > className="com.user.rdbms.CompanyTable"
    > >> >> dbEntityName="company_table">
    > >> >> <obj-attribute name="code" type="java.lang.Integer"
    > >> >> db-attribute-path="code"/>
    > >> >> <obj-attribute name="comment" type="java.lang.String"
    > >> >> db-attribute-path="comment"/>
    > >> >> <obj-attribute name="companyName" type="java.lang.String"
    > >> >> db-attribute-path="company_name"/>
    > >> >> <obj-attribute name="companyUuid" type="java.util.UUID"
    > >> >> db-attribute-path="company_uuid"/>
    > >> >> ....and so on
    > >> >>
    > >> >> <db-entity name="company_table">
    > >> >> <db-attribute name="code" type="INTEGER" length="10"/>
    > >> >> <db-attribute name="comment" type="CLOB" length="2147483647"/>
    > >> >> <db-attribute name="company_name" type="VARCHAR" length="50"/>
    > >> >> <db-attribute name="company_uuid" type="OTHER" length="2147483647"/>
    > >> >> ....and so on
    > >> >>
    > >> >> <db-relationship name="toCompanyTable" source="user_table"
    > >> >> target="company_table" toMany="false">
    > >> >> <db-attribute-pair source="company_name" target="company_name"/>
    > >> >> </db-relationship>
    > >> >>
    > >> >> and user_table has a company_name which is used as the unqiue key to
    > >> >> retrieve the relevant company from the user.
    > >> >>
    > >> >> So then....
    > >> >>
    > >> >> protected UserTable getUser() {
    > >> >> if(context == null){
    > >> >> this.context = ContextCreator.makeContext(..., ..., ...); //with
    > >> >> real values for "..."
    > >> >> }
    > >> >> if(user == null){
    > >> >> Expression exp =
    > >> >> ExpressionFactory.matchExp(UserTable.USER_UUID_PROPERTY,
    > >> >> userUUID);
    > >> >> SelectQuery select = new SelectQuery(UserTable.class, exp);
    > >> >> user = (UserTable) DataObjectUtils.objectForQuery(context, select);
    > >> >> if(user == null) throw new IllegalStateException("user " +
    > userUUID +
    > >> "
    > >> >> not found);
    > >> >> }
    > >> >> return user;
    > >> >> }
    > >> >>
    > >> >> And then...
    > >> >>
    > >> >> protected CompanyTable getCompany() {
    > >> >> if(company == null){
    > >> >> company = getUser().getToCompanyTable();
    > >> >> if(company == null) throw new IllegalStateException("Company not
    > found
    > >> >> for user " + getUser().getUserUuid());
    > >> >> }
    > >> >> return company;
    > >> >> }
    > >> >>
    > >> >>
    > >> >> And I can use user.getUserUuid() with no problems, but if I try to do
    > >> >> company.getCompanyUuid() where company was retrieved using
    > >> >> user.getToCompanyTable() it bombs as though the ExtendedTypes aren't
    > >> >> there.
    > >> >>
    > >> >> I hope this isn't too much to dig through....
    > >> >>
    > >> >> Thanks again for taking a peek...
    > >> >>
    > >> >
    > >>
    > >
    >



    This archive was generated by hypermail 2.0.0 : Fri Aug 01 2008 - 15:18:23 EDT