The observed error where a query containing a externalized field fails during 
parameter validation seems to be a genuine bug.

> org.apache.openjpa.persistence.ArgumentException: The parameter "0" is of 
> type "java.util.UUID", but the declaration in the query is for type 
> "java.lang.String".
>    at 
> org.apache.openjpa.persistence.QueryImpl.validateParameter(QueryImpl.java:270)


Externalization of field values is a OpenJPA-specific feature and hence its 
usage/restrictions vis-a-vis JPA specification requires some discussion.

Here is a typical example: A field 'uuid' is declared as of type java.util.UUID 
but externalized as java.lang.String.

@Persistent
   @Column(nullable=false)
   @Externalizer("toString")        // non-static method
   @Factory("UUID.fromString")   // static method
   private UUID uuid;


When this field is used in query predicate and a parameter is bound, what 
should be the allowed runtime type of the parameter?
The delared type of the field (i.e. java.util.UUID) or the externalized type 
(i.e. java.lang.String) or both?


Object param = ... // what should be the runtime type of a binding parameter?
Query query = em.createQuery("SELECT a FROM External a WHERE a.uuid = ?1");
query.setParameter(1, param);

Here is snippet from Section 4.6.4.1 "Positional Parameters" of JPA 1.0 Spec:
"An input parameter evaluates to the abstract schema type of the corresponding 
parameter defined in the signature of the finder or select method with which 
the query is associated. It is the responsibility of the persistence provider 
to map the input parameter to the appropriate abstract schema type value".  

Subjected to our interpretaion of "evaluates", the above directive seems to 
suggest that the runtime type of the binding parameter can be either 
java.util.UUID or java.lang.String. And OpenJPA documentation also seems to 
agree.

However, with current implementation it may be non-trivial to validate the 
query parameter at JPA-façade layer for *both* types. It is rather prudent to 
restrict the user-supplied binding parameter be of declared type only (i.e. 
java.util.UUID) and not the externalized type (i.e. java.lang.String).    

However, the current code does not cover the externalized fields in either 
case. If the binding parameter is   java.util.UUID type, the validation break 
with the reported exception. A java.lang.String type binding parameter passes 
the validation phase but breaks later during data conversion. 



-----Original Message-----
From: Kevin Sutter [mailto:[EMAIL PROTECTED] 
Sent: Wednesday, April 30, 2008 2:31 PM
To: [email protected]
Subject: Re: UUIDs

Nikolas,
Fair enough.  From my understanding of these Externalizers, I would define your 
UUID field as follows:

   @Persistent
   @Column(nullable=false)
   @Externalizer("toString")        // non-static method
   @Factory("UUID.fromString")   // static method
   private UUID uuid;

OpenJPA should just use the UUID methods to go to and from the string 
presentation.  The @ElementType annotation should not be necessary since you 
don't seem to be processing a Collection of UUIDs.  These seem to be single 
instances of UUIDs.

Have you tried this particular combination?  I haven't made the connection 
between these changes and your specific error message, but let's make sure 
we're consistent with our understanding.  Thanks.

Kevin

On Wed, Apr 30, 2008 at 2:09 PM, Nikolas Everett <[EMAIL PROTECTED]> wrote:

> Kevin,
>
> Thanks for getting back to me.
>
> Thats a cool generator.  I might use that sometime.  Unfortunately, 
> the UUIDs are keys into another system.  I'm just trying to get them 
> to persist them into the database as string and load them into java as 
> UUIDs.
>
> Thanks again,
>
> --Nik
>
> On Wed, Apr 30, 2008 at 2:57 PM, Kevin Sutter <[EMAIL PROTECTED]> wrote:
>
> > :-)  Quiet doesn't mean we're not busy...  :-)
> >
> > My first thought when I read your append is why are you not just 
> > using
> the
> > built-in UUID generator that OpenJPA provides?  OpenJPA allows you 
> > to
> use
> > a
> > generator on non-id fields.  We can either generate the UUID as a 16 
> > character string or a 32 character hex value.  Would this usage 
> > suffice for you, or do you have some other requirements for the use 
> > of the externalizer?
> >
> > Here's a link to the documentation on the UUID generator:
> >
> >
> http://openjpa.apache.org/docs/latest/manual/manual.html#jpa_overview_
> meta_gen
> >
> > Kevin
> >
> > On Wed, Apr 30, 2008 at 9:49 AM, Nikolas Everett <[EMAIL PROTECTED]>
> > wrote:
> >
> > > I tried the attached message on the users list but didn't get any 
> > > response.
> > > Will someone on the dev listserve help?  I'm researching an ORM
> solution
> > > for
> > > our company, and can't in good conscience pick one with quiet
> listservs.
> > > Thanks,
> > >
> > > --Nik
> > >
> > > ---------- Forwarded message ----------
> > > From: Nikolas Everett <[EMAIL PROTECTED]>
> > > Date: Mon, Apr 28, 2008 at 5:20 PM
> > > Subject: UUIDs
> > > To: [EMAIL PROTECTED]
> > >
> > >
> > > I tried to search the archives and didn't find anything on this.  
> > > I'm using openjpa 1.0.2 and having problems with UUIDs backed into 
> > > postgres 8.2.
> > >
> > > I have a class like:
> > > @Entity
> > > @Table([EMAIL PROTECTED](columnNames="uuid")})
> > > public class Account {
> > >    @Id
> > >    @GeneratedValue(strategy=GenerationType.IDENTITY)
> > >    private int id;
> > >
> > >    @Persistent
> > >    @Column(nullable=false)
> > >    @Externalizer("java.util.UUID.toString")
> > >    @Factory("java.util.UUID.fromString")
> > >    @ElementType(UUID.class)
> > >    private UUID uuid;
> > >
> > > ...getters and setters...
> > > }
> > >
> > > The uuid column is created as a character varying 255, which is 
> > > fine
> for
> > > now.
> > >
> > > I  have a method like this:
> > >    protected Account getAccountByUuid(UUID uuid) {
> > >        Query findAccount = this.em.createQuery("SELECT a FROM 
> > > Account
> a
> > > WHERE a.uuid = ?1");
> > >        findAccount.setParameter(1, uuid);
> > >        try {
> > >            return (Account) findAccount.getSingleResult();
> > >        } catch (NoResultException e) {
> > >            Account account = new Account();
> > >            account.setUuid(uuid);
> > >            this.em.persist(account);
> > >            return account;
> > >        }
> > >    }
> > >
> > > Which throws an exception like this:
> > > Exception in thread "main" <openjpa-1.0.2-r420667:627158 nonfatal 
> > > user
> > > error> org.apache.openjpa.persistence.ArgumentException: The 
> > > error> parameter
> > "0"
> > > is of type "java.util.UUID", but the declaration in the query is 
> > > for
> > type
> > > "java.lang.String".
> > >    at
> > >
> > >
> >
> org.apache.openjpa.persistence.QueryImpl.validateParameter(QueryImpl.j
> ava:270)
> > >    at
> > >
> > >
> >
> org.apache.openjpa.persistence.QueryImpl.validateParameters(QueryImpl.
> java:250)
> > >    at
> > org.apache.openjpa.persistence.QueryImpl.execute(QueryImpl.java:231)
> > >    at
> > >
> > >
> >
> org.apache.openjpa.persistence.QueryImpl.getSingleResult(QueryImpl.jav
> a:300)
> > >    at 
> > > com.companyname.Classname.getAccountByUuid(FetchData.java:73)
> > >
> > > This isn't the behavior documented here:
> > >
> > >
> >
> http://openjpa.apache.org/docs/latest/manual/ref_guide_pc_scos.html#d0
> e21916
> > >
> > > What can I do?
> > >
> > > Thanks in advance,
> > >
> > > --Nik
> > >
> >
>

Notice:  This email message, together with any attachments, may contain 
information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated 
entities,  that may be confidential,  proprietary,  copyrighted  and/or legally 
privileged, and is intended solely for the use of the individual or entity 
named in this message. If you are not the intended recipient, and have received 
this message in error, please immediately return this by email and then delete 
it.

Reply via email to