You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cayenne.apache.org by Mike Kienenberger <mk...@gmail.com> on 2011/10/04 01:53:42 UTC

Re: [jira] [Commented] (CAY-1622) Generated classes shouldn't produce serialVersionUID compiler warning

No, it should be more clever than that.  Otherwise, every time you
regenerate the template, the generated code will change even if
nothing else had changed.   That will also break serialization.

Ideally, it should return the same number whenever the same fields and
types are used for the generated class.

Maybe build the number by iterating over the attributes and
relationships and feeding it into
org.apache.commons.lang.builder.HashCodeBuilder, basing it on the
order and type


On Mon, Oct 3, 2011 at 7:41 PM, Ari Maniatis (Commented) (JIRA)
<ji...@apache.org> wrote:
>
>    [ https://issues.apache.org/jira/browse/CAY-1622?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13119757#comment-13119757 ]
>
> Ari Maniatis commented on CAY-1622:
> -----------------------------------
>
> Do we just want to add this to the velocity templates:
>
> private static final long serialVersionUID = ${random(1,9223372036854775807)};
>
>> Generated classes shouldn't produce serialVersionUID compiler warning
>> ---------------------------------------------------------------------
>>
>>                 Key: CAY-1622
>>                 URL: https://issues.apache.org/jira/browse/CAY-1622
>>             Project: Cayenne
>>          Issue Type: Bug
>>          Components: Core Library
>>    Affects Versions: 3.0
>>            Reporter: Bob Harner
>>            Priority: Minor
>>
>> It is probably a good idea for Cayenne not to produce any compiler warnings, but auto-generated entity classes always have the "The serializable class _Foo does not declare a static final serialVersionUID field of type long" compiler warning.
>> The @SuppressWarnings("serial") annotation will get rid of the warnings, but of course it is not recommended to manually update the generated  classes.
>> Users could configure the IDE to ignore these warnings (yuk), but then other team members will still see them.
>> Another option is to for users to set up a custom velocity template to include this annotation.
>> But the best solution would be for Cayenne to either automatically generate either the serialVersionUID itself or the @SuppressWarnings("serial") annotation that suppresses the compiler warning.
>
> --
> This message is automatically generated by JIRA.
> If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
> For more information on JIRA, see: http://www.atlassian.com/software/jira
>
>
>

Re: [jira] [Commented] (CAY-1622) Generated classes shouldn't produce serialVersionUID compiler warning

Posted by Aristedes Maniatis <ar...@maniatis.org>.
I find that the cgen task does not regenerate the files unless the cayenne model has an updated datetime stamp. However, your point is taken that this will then cause ALL entities to get a new serial number, even if only one changed.

Ari


On 4/10/11 10:53 AM, Mike Kienenberger wrote:
> No, it should be more clever than that.  Otherwise, every time you
> regenerate the template, the generated code will change even if
> nothing else had changed.   That will also break serialization.
>
> Ideally, it should return the same number whenever the same fields and
> types are used for the generated class.
>
> Maybe build the number by iterating over the attributes and
> relationships and feeding it into
> org.apache.commons.lang.builder.HashCodeBuilder, basing it on the
> order and type
>
>
> On Mon, Oct 3, 2011 at 7:41 PM, Ari Maniatis (Commented) (JIRA)
> <ji...@apache.org>  wrote:
>>
>>     [ https://issues.apache.org/jira/browse/CAY-1622?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13119757#comment-13119757 ]
>>
>> Ari Maniatis commented on CAY-1622:
>> -----------------------------------
>>
>> Do we just want to add this to the velocity templates:
>>
>> private static final long serialVersionUID = ${random(1,9223372036854775807)};
>>
>>> Generated classes shouldn't produce serialVersionUID compiler warning
>>> ---------------------------------------------------------------------
>>>
>>>                  Key: CAY-1622
>>>                  URL: https://issues.apache.org/jira/browse/CAY-1622
>>>              Project: Cayenne
>>>           Issue Type: Bug
>>>           Components: Core Library
>>>     Affects Versions: 3.0
>>>             Reporter: Bob Harner
>>>             Priority: Minor
>>>
>>> It is probably a good idea for Cayenne not to produce any compiler warnings, but auto-generated entity classes always have the "The serializable class _Foo does not declare a static final serialVersionUID field of type long" compiler warning.
>>> The @SuppressWarnings("serial") annotation will get rid of the warnings, but of course it is not recommended to manually update the generated  classes.
>>> Users could configure the IDE to ignore these warnings (yuk), but then other team members will still see them.
>>> Another option is to for users to set up a custom velocity template to include this annotation.
>>> But the best solution would be for Cayenne to either automatically generate either the serialVersionUID itself or the @SuppressWarnings("serial") annotation that suppresses the compiler warning.
>>
>> --
>> This message is automatically generated by JIRA.
>> If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
>> For more information on JIRA, see: http://www.atlassian.com/software/jira
>>
>>
>>

-- 
-------------------------->
Aristedes Maniatis
GPG fingerprint CBFB 84B4 738D 4E87 5E5C  5EFA EF6A 7D2E 3E49 102A

RE: [jira] [Commented] (CAY-1622) Generated classes shouldn't produce serialVersionUID compiler warning

Posted by "Durchholz, Joachim" <Jo...@hennig-fahrzeugteile.de>.
> This is a separate task (not that it is not important), so I'd not mix it with serialVersionUID discussion. 

OK :-)

> I have similar ideas about changing internal structure of CayenneDataObject (using [] instead of a map).

That would definitely require some serious performance measurements.

The other data structure I have been thinking about is the objects themselves, and using Method objects to access the fields when by-name access or iterating over all fields is required. (I shamelessly stole that approach from org.apache.commons.beanutils.PropertyUtilsBean, which has to solve similar problems.)

Just a whacko idea I've been playing with, I have no idea whether it will be truly faster. Method#invoke looks like it could be optimizable, but maybe not well enough to actually beat array access plus run-time type cast.
So: more performance testing :-)

Regards,
Jo

Re: [jira] [Commented] (CAY-1622) Generated classes shouldn't produce serialVersionUID compiler warning

Posted by Andrus Adamchik <an...@objectstyle.org>.
This is a separate task (not that it is not important), so I'd not mix it with serialVersionUID discussion. 

I have similar ideas about changing internal structure of CayenneDataObject (using [] instead of a map). This is a big change (and should give a big performance boost not just during serialization, but in general), but that is more of a long term future...

Andrus

On Oct 4, 2011, at 6:39 PM, Durchholz, Joachim wrote:

> If the plan is to get the whole serialization stuff right at this time, maybe it's best to go the extra mile and avoid serializing the Map keys.
> 
> Prerequisite 1: You need to know the field names, both on the sending and the receiving end.
> 
> Prerequisite 2: You need a way to iterate over all field values, in the same order as the field names; or you need a way to access the field values given a field name in String form.
> 
> If these are given, you can transfer just the values and do not need to transfer the keys.
> 
> Win: Halve the amount of data that needs to be transferred. Give or take a few, depending on circumstances.
> 
> Maybe win: If you're taking the format of serialized data into your own hands, it could be made identical for the ROP and non-ROP case. This would make it easy to record serialized data in one environment and replay it in another, which might help folks who are setting up diagnostics and unit tests.
> 
> Nonproblem: Now that SerialVersionUID takes care that the field structure and hence the Map keys are the same on both sides, transferring keys is indeed redundant.
> 
> Disclaimer: I know next to nothing about the internals of Cayenne, so this may be much work than it's worth.
> 
> So, just my 2 cents worth here.
> 
> Regards,
> Jo
> 


RE: [jira] [Commented] (CAY-1622) Generated classes shouldn't produce serialVersionUID compiler warning

Posted by "Durchholz, Joachim" <Jo...@hennig-fahrzeugteile.de>.
If the plan is to get the whole serialization stuff right at this time, maybe it's best to go the extra mile and avoid serializing the Map keys.

Prerequisite 1: You need to know the field names, both on the sending and the receiving end.

Prerequisite 2: You need a way to iterate over all field values, in the same order as the field names; or you need a way to access the field values given a field name in String form.

If these are given, you can transfer just the values and do not need to transfer the keys.

Win: Halve the amount of data that needs to be transferred. Give or take a few, depending on circumstances.

Maybe win: If you're taking the format of serialized data into your own hands, it could be made identical for the ROP and non-ROP case. This would make it easy to record serialized data in one environment and replay it in another, which might help folks who are setting up diagnostics and unit tests.

Nonproblem: Now that SerialVersionUID takes care that the field structure and hence the Map keys are the same on both sides, transferring keys is indeed redundant.

Disclaimer: I know next to nothing about the internals of Cayenne, so this may be much work than it's worth.

So, just my 2 cents worth here.

Regards,
Jo

Re: [jira] [Commented] (CAY-1622) Generated classes shouldn't produce serialVersionUID compiler warning

Posted by Dzmitry Kazimirchyk <dk...@gmail.com>.
Now everything is pretty clear about ROP client classes. But what 
algorithm should we use for server classes UID generation? Suppose it 
probably must be somehow related with CayenneDataObject class version...

On 10/04/2011 11:25 AM, Andrus Adamchik wrote:
> Actually... since CayenneDataObject is a Map, do we even care about attributes and relationships? No matter what they are, serialization format should stay the same..
>
> Now we also have ROP where objects are NOT maps. So we need a different algorithm for those , which is more like the one you implemented (+ my suggestion about relationship type ... for to-one)
>
> That means that we need 2 different algorithms used in server and ROP templates.
>
> Andrus
>
>
>
> On Oct 4, 2011, at 11:19 AM, Andrus Adamchik wrote:
>> Very cool.
>>
>> Can we also create some unit tests for this to ensure it works as advertised. E.g. a possible caveat is consistent alphabetic ordering of relationships and attributes (IIRC they are ordered by default, but it is worth creating some tests to see how entity creation affects the result). Also I think in relationships loop we may add a check for the target entity type.
>>
>> Andrus
>>
>>
>>
>> On Oct 4, 2011, at 11:10 AM, Dzmitry Kazimirchyk wrote:
>>
>>> Just committed fix to the trunk (r1178712). UID generation algorithm uses same approach as java.io.ObjectStreamClass.getSerialVersionUID(). Generated id depends on ObjEntity's superclass, ObjAttributes and ObjRelationships names and types.
>>>
>>> Here is the diff:
>>>
>>> Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java
>>> URL:http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java?rev=1178712&r1=1178711&r2=1178712&view=diff
>>> ==============================================================================
>>> --- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java (original)
>>> +++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java Tue Oct  4 07:57:40 2011
>>> @@ -19,6 +19,9 @@
>>>
>>> package org.apache.cayenne.map;
>>>
>>> +import java.io.ByteArrayOutputStream;
>>> +import java.io.DataOutputStream;
>>> +import java.security.MessageDigest;
>>> import java.util.ArrayList;
>>> import java.util.Arrays;
>>> import java.util.Collection;
>>> @@ -1250,5 +1253,42 @@ public class ObjEntity extends Entity im
>>>     public void setExcludingSuperclassListeners(boolean excludingSuperclassListeners) {
>>>         this.excludingSuperclassListeners = excludingSuperclassListeners;
>>>     }
>>> +
>>> +    /**
>>> +     * Returns unique id for this ObjEntity.
>>> +     *
>>> +     * @since 3.1
>>> +     */
>>> +    public long getSerialVersionUID() throws Exception {
>>> +        ByteArrayOutputStream bout = new ByteArrayOutputStream();
>>> +        DataOutputStream dout = new DataOutputStream(bout);
>>> +
>>> +        dout.writeUTF(getClassName());
>>> +
>>> +        if (getSuperClassName() != null) {
>>> +            dout.writeUTF(getSuperClassName());
>>> +        }
>>> +
>>> +        for (ObjAttribute attr : getAttributes()) {
>>> +            dout.writeUTF(attr.getName());
>>> +            dout.writeUTF(attr.getType());
>>> +        }
>>> +
>>> +        for (ObjRelationship rel : getRelationships()) {
>>> +            dout.writeUTF(rel.getName());
>>> +            dout.writeUTF(rel.getCollectionType() != null
>>> +                    ? rel.getCollectionType() : "to-one");
>>> +        }
>>> +
>>> +        dout.flush();
>>> +
>>> +        MessageDigest md = MessageDigest.getInstance("SHA");
>>> +        byte[] hashBytes = md.digest(bout.toByteArray());
>>> +        long hash = 0;
>>> +        for (int i = Math.min(hashBytes.length, 8) - 1; i>= 0; i--) {
>>> +            hash = (hash<<   8) | (hashBytes[i]&   0xFF);
>>> +        }
>>> +        return hash;
>>> +    }
>>>
>>> }
>>>
>>>
>>> Dzmitry
>>>
>>> On 10/04/2011 08:22 AM, Andrus Adamchik wrote:
>>>> +1. We had a brief discussion with Dzmitry to that extent last night. Here is an extract from that chat:
>>>>
>>>>> Generated classes (the ones with _XXX) are made from ObjEntities, so if we can use an alg. based on ObjEntity state, I think that should be enough just need to account for all its parts (superclass, objattribute names and types; objrelationship names and types)
>>>> So yeah, IMO it does have to be like hashcode of sorts based on ObjEntity state...
>>>>
>>>> Andrus
>>>>
>>>> On Oct 4, 2011, at 2:53 AM, Mike Kienenberger wrote:
>>>>
>>>>> No, it should be more clever than that.  Otherwise, every time you
>>>>> regenerate the template, the generated code will change even if
>>>>> nothing else had changed.   That will also break serialization.
>>>>>
>>>>> Ideally, it should return the same number whenever the same fields and
>>>>> types are used for the generated class.
>>>>>
>>>>> Maybe build the number by iterating over the attributes and
>>>>> relationships and feeding it into
>>>>> org.apache.commons.lang.builder.HashCodeBuilder, basing it on the
>>>>> order and type
>>>>>
>>>>>
>>>>> On Mon, Oct 3, 2011 at 7:41 PM, Ari Maniatis (Commented) (JIRA)
>>>>> <ji...@apache.org>   wrote:
>>>>>>   [ https://issues.apache.org/jira/browse/CAY-1622?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13119757#comment-13119757 ]
>>>>>>
>>>>>> Ari Maniatis commented on CAY-1622:
>>>>>> -----------------------------------
>>>>>>
>>>>>> Do we just want to add this to the velocity templates:
>>>>>>
>>>>>> private static final long serialVersionUID = ${random(1,9223372036854775807)};
>>>>>>
>>>>>>> Generated classes shouldn't produce serialVersionUID compiler warning
>>>>>>> ---------------------------------------------------------------------
>>>>>>>
>>>>>>>                Key: CAY-1622
>>>>>>>                URL: https://issues.apache.org/jira/browse/CAY-1622
>>>>>>>            Project: Cayenne
>>>>>>>         Issue Type: Bug
>>>>>>>         Components: Core Library
>>>>>>>   Affects Versions: 3.0
>>>>>>>           Reporter: Bob Harner
>>>>>>>           Priority: Minor
>>>>>>>
>>>>>>> It is probably a good idea for Cayenne not to produce any compiler warnings, but auto-generated entity classes always have the "The serializable class _Foo does not declare a static final serialVersionUID field of type long" compiler warning.
>>>>>>> The @SuppressWarnings("serial") annotation will get rid of the warnings, but of course it is not recommended to manually update the generated  classes.
>>>>>>> Users could configure the IDE to ignore these warnings (yuk), but then other team members will still see them.
>>>>>>> Another option is to for users to set up a custom velocity template to include this annotation.
>>>>>>> But the best solution would be for Cayenne to either automatically generate either the serialVersionUID itself or the @SuppressWarnings("serial") annotation that suppresses the compiler warning.
>>>>>> --
>>>>>> This message is automatically generated by JIRA.
>>>>>> If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
>>>>>> For more information on JIRA, see: http://www.atlassian.com/software/jira
>>>>>>
>>>>>>
>>>>>>
>>>
>>


Re: [jira] [Commented] (CAY-1622) Generated classes shouldn't produce serialVersionUID compiler warning

Posted by Andrus Adamchik <an...@objectstyle.org>.
Actually... since CayenneDataObject is a Map, do we even care about attributes and relationships? No matter what they are, serialization format should stay the same..

Now we also have ROP where objects are NOT maps. So we need a different algorithm for those , which is more like the one you implemented (+ my suggestion about relationship type ... for to-one)

That means that we need 2 different algorithms used in server and ROP templates.

Andrus



On Oct 4, 2011, at 11:19 AM, Andrus Adamchik wrote:
> Very cool. 
> 
> Can we also create some unit tests for this to ensure it works as advertised. E.g. a possible caveat is consistent alphabetic ordering of relationships and attributes (IIRC they are ordered by default, but it is worth creating some tests to see how entity creation affects the result). Also I think in relationships loop we may add a check for the target entity type.
> 
> Andrus
> 
> 
> 
> On Oct 4, 2011, at 11:10 AM, Dzmitry Kazimirchyk wrote:
> 
>> Just committed fix to the trunk (r1178712). UID generation algorithm uses same approach as java.io.ObjectStreamClass.getSerialVersionUID(). Generated id depends on ObjEntity's superclass, ObjAttributes and ObjRelationships names and types.
>> 
>> Here is the diff:
>> 
>> Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java
>> URL:http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java?rev=1178712&r1=1178711&r2=1178712&view=diff
>> ==============================================================================
>> --- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java (original)
>> +++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java Tue Oct  4 07:57:40 2011
>> @@ -19,6 +19,9 @@
>> 
>> package org.apache.cayenne.map;
>> 
>> +import java.io.ByteArrayOutputStream;
>> +import java.io.DataOutputStream;
>> +import java.security.MessageDigest;
>> import java.util.ArrayList;
>> import java.util.Arrays;
>> import java.util.Collection;
>> @@ -1250,5 +1253,42 @@ public class ObjEntity extends Entity im
>>    public void setExcludingSuperclassListeners(boolean excludingSuperclassListeners) {
>>        this.excludingSuperclassListeners = excludingSuperclassListeners;
>>    }
>> +
>> +    /**
>> +     * Returns unique id for this ObjEntity.
>> +     *
>> +     * @since 3.1
>> +     */
>> +    public long getSerialVersionUID() throws Exception {
>> +        ByteArrayOutputStream bout = new ByteArrayOutputStream();
>> +        DataOutputStream dout = new DataOutputStream(bout);
>> +
>> +        dout.writeUTF(getClassName());
>> +
>> +        if (getSuperClassName() != null) {
>> +            dout.writeUTF(getSuperClassName());
>> +        }
>> +
>> +        for (ObjAttribute attr : getAttributes()) {
>> +            dout.writeUTF(attr.getName());
>> +            dout.writeUTF(attr.getType());
>> +        }
>> +
>> +        for (ObjRelationship rel : getRelationships()) {
>> +            dout.writeUTF(rel.getName());
>> +            dout.writeUTF(rel.getCollectionType() != null
>> +                    ? rel.getCollectionType() : "to-one");
>> +        }
>> +
>> +        dout.flush();
>> +
>> +        MessageDigest md = MessageDigest.getInstance("SHA");
>> +        byte[] hashBytes = md.digest(bout.toByteArray());
>> +        long hash = 0;
>> +        for (int i = Math.min(hashBytes.length, 8) - 1; i>= 0; i--) {
>> +            hash = (hash<<  8) | (hashBytes[i]&  0xFF);
>> +        }
>> +        return hash;
>> +    }
>> 
>> }
>> 
>> 
>> Dzmitry
>> 
>> On 10/04/2011 08:22 AM, Andrus Adamchik wrote:
>>> +1. We had a brief discussion with Dzmitry to that extent last night. Here is an extract from that chat:
>>> 
>>>> Generated classes (the ones with _XXX) are made from ObjEntities, so if we can use an alg. based on ObjEntity state, I think that should be enough just need to account for all its parts (superclass, objattribute names and types; objrelationship names and types)
>>> So yeah, IMO it does have to be like hashcode of sorts based on ObjEntity state...
>>> 
>>> Andrus
>>> 
>>> On Oct 4, 2011, at 2:53 AM, Mike Kienenberger wrote:
>>> 
>>>> No, it should be more clever than that.  Otherwise, every time you
>>>> regenerate the template, the generated code will change even if
>>>> nothing else had changed.   That will also break serialization.
>>>> 
>>>> Ideally, it should return the same number whenever the same fields and
>>>> types are used for the generated class.
>>>> 
>>>> Maybe build the number by iterating over the attributes and
>>>> relationships and feeding it into
>>>> org.apache.commons.lang.builder.HashCodeBuilder, basing it on the
>>>> order and type
>>>> 
>>>> 
>>>> On Mon, Oct 3, 2011 at 7:41 PM, Ari Maniatis (Commented) (JIRA)
>>>> <ji...@apache.org>  wrote:
>>>>>  [ https://issues.apache.org/jira/browse/CAY-1622?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13119757#comment-13119757 ]
>>>>> 
>>>>> Ari Maniatis commented on CAY-1622:
>>>>> -----------------------------------
>>>>> 
>>>>> Do we just want to add this to the velocity templates:
>>>>> 
>>>>> private static final long serialVersionUID = ${random(1,9223372036854775807)};
>>>>> 
>>>>>> Generated classes shouldn't produce serialVersionUID compiler warning
>>>>>> ---------------------------------------------------------------------
>>>>>> 
>>>>>>               Key: CAY-1622
>>>>>>               URL: https://issues.apache.org/jira/browse/CAY-1622
>>>>>>           Project: Cayenne
>>>>>>        Issue Type: Bug
>>>>>>        Components: Core Library
>>>>>>  Affects Versions: 3.0
>>>>>>          Reporter: Bob Harner
>>>>>>          Priority: Minor
>>>>>> 
>>>>>> It is probably a good idea for Cayenne not to produce any compiler warnings, but auto-generated entity classes always have the "The serializable class _Foo does not declare a static final serialVersionUID field of type long" compiler warning.
>>>>>> The @SuppressWarnings("serial") annotation will get rid of the warnings, but of course it is not recommended to manually update the generated  classes.
>>>>>> Users could configure the IDE to ignore these warnings (yuk), but then other team members will still see them.
>>>>>> Another option is to for users to set up a custom velocity template to include this annotation.
>>>>>> But the best solution would be for Cayenne to either automatically generate either the serialVersionUID itself or the @SuppressWarnings("serial") annotation that suppresses the compiler warning.
>>>>> --
>>>>> This message is automatically generated by JIRA.
>>>>> If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
>>>>> For more information on JIRA, see: http://www.atlassian.com/software/jira
>>>>> 
>>>>> 
>>>>> 
>> 
>> 
> 
> 


Re: [jira] [Commented] (CAY-1622) Generated classes shouldn't produce serialVersionUID compiler warning

Posted by Andrus Adamchik <an...@objectstyle.org>.
Very cool. 

Can we also create some unit tests for this to ensure it works as advertised. E.g. a possible caveat is consistent alphabetic ordering of relationships and attributes (IIRC they are ordered by default, but it is worth creating some tests to see how entity creation affects the result). Also I think in relationships loop we may add a check for the target entity type.

Andrus



On Oct 4, 2011, at 11:10 AM, Dzmitry Kazimirchyk wrote:

> Just committed fix to the trunk (r1178712). UID generation algorithm uses same approach as java.io.ObjectStreamClass.getSerialVersionUID(). Generated id depends on ObjEntity's superclass, ObjAttributes and ObjRelationships names and types.
> 
> Here is the diff:
> 
> Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java
> URL:http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java?rev=1178712&r1=1178711&r2=1178712&view=diff
> ==============================================================================
> --- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java (original)
> +++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java Tue Oct  4 07:57:40 2011
> @@ -19,6 +19,9 @@
> 
> package org.apache.cayenne.map;
> 
> +import java.io.ByteArrayOutputStream;
> +import java.io.DataOutputStream;
> +import java.security.MessageDigest;
> import java.util.ArrayList;
> import java.util.Arrays;
> import java.util.Collection;
> @@ -1250,5 +1253,42 @@ public class ObjEntity extends Entity im
>     public void setExcludingSuperclassListeners(boolean excludingSuperclassListeners) {
>         this.excludingSuperclassListeners = excludingSuperclassListeners;
>     }
> +
> +    /**
> +     * Returns unique id for this ObjEntity.
> +     *
> +     * @since 3.1
> +     */
> +    public long getSerialVersionUID() throws Exception {
> +        ByteArrayOutputStream bout = new ByteArrayOutputStream();
> +        DataOutputStream dout = new DataOutputStream(bout);
> +
> +        dout.writeUTF(getClassName());
> +
> +        if (getSuperClassName() != null) {
> +            dout.writeUTF(getSuperClassName());
> +        }
> +
> +        for (ObjAttribute attr : getAttributes()) {
> +            dout.writeUTF(attr.getName());
> +            dout.writeUTF(attr.getType());
> +        }
> +
> +        for (ObjRelationship rel : getRelationships()) {
> +            dout.writeUTF(rel.getName());
> +            dout.writeUTF(rel.getCollectionType() != null
> +                    ? rel.getCollectionType() : "to-one");
> +        }
> +
> +        dout.flush();
> +
> +        MessageDigest md = MessageDigest.getInstance("SHA");
> +        byte[] hashBytes = md.digest(bout.toByteArray());
> +        long hash = 0;
> +        for (int i = Math.min(hashBytes.length, 8) - 1; i>= 0; i--) {
> +            hash = (hash<<  8) | (hashBytes[i]&  0xFF);
> +        }
> +        return hash;
> +    }
> 
> }
> 
> 
> Dzmitry
> 
> On 10/04/2011 08:22 AM, Andrus Adamchik wrote:
>> +1. We had a brief discussion with Dzmitry to that extent last night. Here is an extract from that chat:
>> 
>>> Generated classes (the ones with _XXX) are made from ObjEntities, so if we can use an alg. based on ObjEntity state, I think that should be enough just need to account for all its parts (superclass, objattribute names and types; objrelationship names and types)
>> So yeah, IMO it does have to be like hashcode of sorts based on ObjEntity state...
>> 
>> Andrus
>> 
>> On Oct 4, 2011, at 2:53 AM, Mike Kienenberger wrote:
>> 
>>> No, it should be more clever than that.  Otherwise, every time you
>>> regenerate the template, the generated code will change even if
>>> nothing else had changed.   That will also break serialization.
>>> 
>>> Ideally, it should return the same number whenever the same fields and
>>> types are used for the generated class.
>>> 
>>> Maybe build the number by iterating over the attributes and
>>> relationships and feeding it into
>>> org.apache.commons.lang.builder.HashCodeBuilder, basing it on the
>>> order and type
>>> 
>>> 
>>> On Mon, Oct 3, 2011 at 7:41 PM, Ari Maniatis (Commented) (JIRA)
>>> <ji...@apache.org>  wrote:
>>>>   [ https://issues.apache.org/jira/browse/CAY-1622?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13119757#comment-13119757 ]
>>>> 
>>>> Ari Maniatis commented on CAY-1622:
>>>> -----------------------------------
>>>> 
>>>> Do we just want to add this to the velocity templates:
>>>> 
>>>> private static final long serialVersionUID = ${random(1,9223372036854775807)};
>>>> 
>>>>> Generated classes shouldn't produce serialVersionUID compiler warning
>>>>> ---------------------------------------------------------------------
>>>>> 
>>>>>                Key: CAY-1622
>>>>>                URL: https://issues.apache.org/jira/browse/CAY-1622
>>>>>            Project: Cayenne
>>>>>         Issue Type: Bug
>>>>>         Components: Core Library
>>>>>   Affects Versions: 3.0
>>>>>           Reporter: Bob Harner
>>>>>           Priority: Minor
>>>>> 
>>>>> It is probably a good idea for Cayenne not to produce any compiler warnings, but auto-generated entity classes always have the "The serializable class _Foo does not declare a static final serialVersionUID field of type long" compiler warning.
>>>>> The @SuppressWarnings("serial") annotation will get rid of the warnings, but of course it is not recommended to manually update the generated  classes.
>>>>> Users could configure the IDE to ignore these warnings (yuk), but then other team members will still see them.
>>>>> Another option is to for users to set up a custom velocity template to include this annotation.
>>>>> But the best solution would be for Cayenne to either automatically generate either the serialVersionUID itself or the @SuppressWarnings("serial") annotation that suppresses the compiler warning.
>>>> --
>>>> This message is automatically generated by JIRA.
>>>> If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
>>>> For more information on JIRA, see: http://www.atlassian.com/software/jira
>>>> 
>>>> 
>>>> 
> 
> 


Re: [jira] [Commented] (CAY-1622) Generated classes shouldn't produce serialVersionUID compiler warning

Posted by Dzmitry Kazimirchyk <dk...@gmail.com>.
Just committed fix to the trunk (r1178712). UID generation algorithm 
uses same approach as java.io.ObjectStreamClass.getSerialVersionUID(). 
Generated id depends on ObjEntity's superclass, ObjAttributes and 
ObjRelationships names and types.

Here is the diff:

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java
URL:http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java?rev=1178712&r1=1178711&r2=1178712&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java Tue Oct  4 07:57:40 2011
@@ -19,6 +19,9 @@

  package org.apache.cayenne.map;

+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.security.MessageDigest;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collection;
@@ -1250,5 +1253,42 @@ public class ObjEntity extends Entity im
      public void setExcludingSuperclassListeners(boolean excludingSuperclassListeners) {
          this.excludingSuperclassListeners = excludingSuperclassListeners;
      }
+
+    /**
+     * Returns unique id for this ObjEntity.
+     *
+     * @since 3.1
+     */
+    public long getSerialVersionUID() throws Exception {
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        DataOutputStream dout = new DataOutputStream(bout);
+
+        dout.writeUTF(getClassName());
+
+        if (getSuperClassName() != null) {
+            dout.writeUTF(getSuperClassName());
+        }
+
+        for (ObjAttribute attr : getAttributes()) {
+            dout.writeUTF(attr.getName());
+            dout.writeUTF(attr.getType());
+        }
+
+        for (ObjRelationship rel : getRelationships()) {
+            dout.writeUTF(rel.getName());
+            dout.writeUTF(rel.getCollectionType() != null
+                    ? rel.getCollectionType() : "to-one");
+        }
+
+        dout.flush();
+
+        MessageDigest md = MessageDigest.getInstance("SHA");
+        byte[] hashBytes = md.digest(bout.toByteArray());
+        long hash = 0;
+        for (int i = Math.min(hashBytes.length, 8) - 1; i>= 0; i--) {
+            hash = (hash<<  8) | (hashBytes[i]&  0xFF);
+        }
+        return hash;
+    }

  }


Dzmitry

On 10/04/2011 08:22 AM, Andrus Adamchik wrote:
> +1. We had a brief discussion with Dzmitry to that extent last night. Here is an extract from that chat:
>
>> Generated classes (the ones with _XXX) are made from ObjEntities, so if we can use an alg. based on ObjEntity state, I think that should be enough just need to account for all its parts (superclass, objattribute names and types; objrelationship names and types)
> So yeah, IMO it does have to be like hashcode of sorts based on ObjEntity state...
>
> Andrus
>
> On Oct 4, 2011, at 2:53 AM, Mike Kienenberger wrote:
>
>> No, it should be more clever than that.  Otherwise, every time you
>> regenerate the template, the generated code will change even if
>> nothing else had changed.   That will also break serialization.
>>
>> Ideally, it should return the same number whenever the same fields and
>> types are used for the generated class.
>>
>> Maybe build the number by iterating over the attributes and
>> relationships and feeding it into
>> org.apache.commons.lang.builder.HashCodeBuilder, basing it on the
>> order and type
>>
>>
>> On Mon, Oct 3, 2011 at 7:41 PM, Ari Maniatis (Commented) (JIRA)
>> <ji...@apache.org>  wrote:
>>>    [ https://issues.apache.org/jira/browse/CAY-1622?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13119757#comment-13119757 ]
>>>
>>> Ari Maniatis commented on CAY-1622:
>>> -----------------------------------
>>>
>>> Do we just want to add this to the velocity templates:
>>>
>>> private static final long serialVersionUID = ${random(1,9223372036854775807)};
>>>
>>>> Generated classes shouldn't produce serialVersionUID compiler warning
>>>> ---------------------------------------------------------------------
>>>>
>>>>                 Key: CAY-1622
>>>>                 URL: https://issues.apache.org/jira/browse/CAY-1622
>>>>             Project: Cayenne
>>>>          Issue Type: Bug
>>>>          Components: Core Library
>>>>    Affects Versions: 3.0
>>>>            Reporter: Bob Harner
>>>>            Priority: Minor
>>>>
>>>> It is probably a good idea for Cayenne not to produce any compiler warnings, but auto-generated entity classes always have the "The serializable class _Foo does not declare a static final serialVersionUID field of type long" compiler warning.
>>>> The @SuppressWarnings("serial") annotation will get rid of the warnings, but of course it is not recommended to manually update the generated  classes.
>>>> Users could configure the IDE to ignore these warnings (yuk), but then other team members will still see them.
>>>> Another option is to for users to set up a custom velocity template to include this annotation.
>>>> But the best solution would be for Cayenne to either automatically generate either the serialVersionUID itself or the @SuppressWarnings("serial") annotation that suppresses the compiler warning.
>>> --
>>> This message is automatically generated by JIRA.
>>> If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
>>> For more information on JIRA, see: http://www.atlassian.com/software/jira
>>>
>>>
>>>


Re: [jira] [Commented] (CAY-1622) Generated classes shouldn't produce serialVersionUID compiler warning

Posted by Andrus Adamchik <an...@objectstyle.org>.
+1. We had a brief discussion with Dzmitry to that extent last night. Here is an extract from that chat:

> Generated classes (the ones with _XXX) are made from ObjEntities, so if we can use an alg. based on ObjEntity state, I think that should be enough just need to account for all its parts (superclass, objattribute names and types; objrelationship names and types)

So yeah, IMO it does have to be like hashcode of sorts based on ObjEntity state...

Andrus

On Oct 4, 2011, at 2:53 AM, Mike Kienenberger wrote:

> No, it should be more clever than that.  Otherwise, every time you
> regenerate the template, the generated code will change even if
> nothing else had changed.   That will also break serialization.
> 
> Ideally, it should return the same number whenever the same fields and
> types are used for the generated class.
> 
> Maybe build the number by iterating over the attributes and
> relationships and feeding it into
> org.apache.commons.lang.builder.HashCodeBuilder, basing it on the
> order and type
> 
> 
> On Mon, Oct 3, 2011 at 7:41 PM, Ari Maniatis (Commented) (JIRA)
> <ji...@apache.org> wrote:
>> 
>>   [ https://issues.apache.org/jira/browse/CAY-1622?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13119757#comment-13119757 ]
>> 
>> Ari Maniatis commented on CAY-1622:
>> -----------------------------------
>> 
>> Do we just want to add this to the velocity templates:
>> 
>> private static final long serialVersionUID = ${random(1,9223372036854775807)};
>> 
>>> Generated classes shouldn't produce serialVersionUID compiler warning
>>> ---------------------------------------------------------------------
>>> 
>>>                Key: CAY-1622
>>>                URL: https://issues.apache.org/jira/browse/CAY-1622
>>>            Project: Cayenne
>>>         Issue Type: Bug
>>>         Components: Core Library
>>>   Affects Versions: 3.0
>>>           Reporter: Bob Harner
>>>           Priority: Minor
>>> 
>>> It is probably a good idea for Cayenne not to produce any compiler warnings, but auto-generated entity classes always have the "The serializable class _Foo does not declare a static final serialVersionUID field of type long" compiler warning.
>>> The @SuppressWarnings("serial") annotation will get rid of the warnings, but of course it is not recommended to manually update the generated  classes.
>>> Users could configure the IDE to ignore these warnings (yuk), but then other team members will still see them.
>>> Another option is to for users to set up a custom velocity template to include this annotation.
>>> But the best solution would be for Cayenne to either automatically generate either the serialVersionUID itself or the @SuppressWarnings("serial") annotation that suppresses the compiler warning.
>> 
>> --
>> This message is automatically generated by JIRA.
>> If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
>> For more information on JIRA, see: http://www.atlassian.com/software/jira
>> 
>> 
>> 
>