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 <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]>
> 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 <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]>
> >> wrote:
> >> >> On Thu, Jul 31, 2008 at 12:38 PM, Michael Gentry
> >> >> <[EMAIL PROTECTED]>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...
> >> >>
> >> >
> >>
> >
>

Reply via email to