Re: Wrong mailing list, please ignore

Brendan Duddridge <[email protected]> Tue, 01 Feb 2005 20:59:59 -0700
Newsgroups gmane.comp.web.webobjects.admin
Message-ID <BE259E4F.1D0E6%[email protected]>
> 
> Sorry, wrong mailing list please ignore.

Geez, and I was just about to help you! :-)

Why not try making the method synchronized like this:

public synchronized static Number objectCountWithFetchSpecification(...) {
    ...
}

That will prevent two threads from entering the method at the same time. So
the method will have time to remove the count attribute from the entity
before the next thread enters the method.

Hope that helps!

___________________________

Brendan Duddridge

ClickSpace Interactive Inc.
Suite L100
239 - 10th Ave SE
Calgary, AB  T2G 0V9
Canada
(403) 277-5591
http://www.clickspace.com/


> Message: 1
> Date: Tue, 1 Feb 2005 12:42:01 +1100
> From: Marek Wawrzyczny <[email protected]>
> Subject: Fetching record counts.
> To: [email protected]
> Message-ID: <[email protected]>
> Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed
> 
> Hi all,
> 
> A long time ago I came across Eric Noyau's famous BugTracker, and the
> useful FetchCounting class. Since then we used something similar to
> perform counts in our  application, however recently it has become the
> source of a problem. The source is at the end of the file.
> 
> I have to admit, I don't fully understand how it works, but essentially
> it appears that the target entity is retrieved from the fetch
> specification. Then a additional "count" attribute is added to the
> model to perform the count.
> 
> There are two problems with that solution we have encountered, the
> first one results in the following exception:
> 
> "Exception while trying to save the EOEditingContext during  the
> processing of transaction... Stack trace:
> java.lang.IllegalArgumentException: addAttribute: duplicated attribute
> name: p_objectCountAttribute
> at com.webobjects.eoaccess.EOEntity.addAttribute(EOEntity.java:2153)
> at  
> ish.common.webobjects.utilities.EOFetchCounting.objectCountWithFetchSpec
> ification(EOFetchCounting.java:61)
>      <...>"
> 
> I believe that this is caused due to the variable
> "_objectCountAttribute" being static. I think that two different
> threads are attempting to perform the fetch count 'simultaneously' on
> the same entity. One has already added the "count" attribute when the
> other attempts to do this again.
> 
> The second exception we get is:
> 
> "java.lang.IllegalArgumentException: addAttribute: attribute has a
> different entity
> at com.webobjects.eoaccess.EOEntity.addAttribute(EOEntity.java:2149)
> at  
> ish.common.webobjects.utilities.EOFetchCounting.objectCountWithFetchSpec
> ification(EOFetchCounting.java:61)
>      <...>"
> 
> Here I believe two threads are attempting to perform fetch counts on
> different entities. Since the static "_objectCountAttribute" can only
> be linked to one entity at a time, we get the exception when the second
> thread attempts to add the attribute before the first thread had the
> opportunity to remove it from its entity.
> 
> This is actually where I am stuck. I don't understand the EOModel and
> EOAttribute mechanism very well. One solution I tried was to add the
> count attribute permanently, that crashed the application. So I tried
> creating the attributes on the fly and removing them once finished this
> worked. However, it doesn't appear I can make this thread-safe since
> there is no locking mechanism on the EOModel (I think this is why
> Eric's solution used a static var) and I cannot easily test this
> concept under duress (when the exceptions actually start occurring).
> 
> Can anyone point me in the right direction on this?
> 
> 
> Marek Wawrzyczny
> 
> software engineer
> -------------------------->
> ish group pty ltd
> http://www.ish.com.au
> 7 Darghan St Glebe 2037 Australia
> phone +61 2 9660 1400   fax +61 2 9660 7400
> 
> <<< Code follows >>>
> 
> 
> package ish.common.webobjects.utilities;
> 
> 
> import com.webobjects.foundation.*;
> import com.webobjects.eocontrol.*;
> import com.webobjects.eoaccess.*;
> 
> 
> /**
>   * <p>This class impements methods that allow us to count the number of
>   * rows for a user defined fetch specification.</p>
>   *
>   * <p>The count is performed directly on the database source without
> having to load
>   * them into memory.</p>
>   *
>   * <p>Original code by Eric Noyau. This class has been taken from
> Eric's Bugtracker application.</p>
>   *
>   * @author Eric Noyau
>   * @author Marek Wawrzyczny
>   * @version 1.1
>   */
> 
> public class EOFetchCounting extends Object {
> 
>      private static EOAttribute _objectCountAttribute = null;
> 
> 
> /**
>       * <p>Returns the number of rows metching the fetch
> specifivation.</p>
>       *
>       * @param editingContext - editing context to perform the fetch in
>       * @param fetchSpecification - the fetch specification
>       */
>      public static Number objectCountWithFetchSpecification(
> EOEditingContext editingContext,
> EOFetchSpecification fetchSpecification) {
> 
>          if (fetchSpecification != null) {
>              EOFetchSpecification rawFetchspecification;
> 
>              try {
>                  rawFetchspecification =
> (EOFetchSpecification)fetchSpecification.clone();
>              } catch (Exception e) {
>                  System.out.println("\nException in
> objectCountWithFetchSpecification :\n"+e);
>                  return null;
>              }
> 
>              EOEntity entity =
> EOModelGroup.defaultGroup().entityNamed(rawFetchspecification.entityName
> ());
>              EOQualifier schemaBasedQualifier =
> entity.schemaBasedQualifier(rawFetchspecification.qualifier());
>              EOAttribute attribute =
> EOFetchCounting.objectCountAttribute();
>              NSArray results = null;
>              entity.addAttribute(attribute);
> 
>              // Fix to ensure that fetch counting does not trip the site
> when
>              // the fetch fails for some reason
>              try {
>                  
> rawFetchspecification.setQualifier(schemaBasedQualifier);
>                  rawFetchspecification.setRawRowKeyPaths(new
> NSArray(attribute.name()));
>                  results =
> editingContext.objectsWithFetchSpecification(rawFetchspecification);
>              } finally {
>                  // IMPORTANT!!!
>                  // This needs to run every time, exception or not
>                  entity.removeAttribute(attribute);
>              }
> 
>              if ((results != null) && (results.count() == 1)) {
>                  NSDictionary row = (NSDictionary) results.lastObject();
>                  return (Number)row.objectForKey(attribute.name());
>              }
>          }
> 
>          return null;
>      }
> 
>      /**
>       * Returns the number of rows metching the fetch specifivation.
>       *
>       * @param editingContext - editing context to perform the fetch in
>       * @param entityName - the entity to perform the count on
>       * @param fetchSpecification - the fetch specification
>       * @param bindings - the fetch bindings
>       */
>      public static Number objectCountWithFetchSpecificationAndBindings(
> EOEditingContext editingContext,
> String entityName,
> String fetchSpecName,
> NSDictionary bindings) {
> 
>          EOModelGroup modelGroup = EOModelGroup.defaultGroup();
>          EOFetchSpecification unboundFetchSpec;
>          EOFetchSpecification boundFetchSpec;
>          unboundFetchSpec =
> modelGroup.fetchSpecificationNamed(fetchSpecName, entityName);
>          if (unboundFetchSpec == null) {
>              return null;
>          }
>          boundFetchSpec =
> unboundFetchSpec.fetchSpecificationWithQualifierBindings(bindings);
>          return objectCountWithFetchSpecification(editingContext,
> boundFetchSpec);
>      }
> 
>      /**
>       * <p>Private.</p>
>       */
>      private static EOAttribute objectCountAttribute() {
> 
>          if ( _objectCountAttribute == null ) {
>              _objectCountAttribute = new EOAttribute();
>              _objectCountAttribute.setName("p_objectCountAttribute");
>               
> _objectCountAttribute.setColumnName("p_objectCountAttribute");
>              _objectCountAttribute.setClassName("Number");
>              _objectCountAttribute.setValueType("i");
>              _objectCountAttribute.setReadFormat("count(*)");
>          }
> 
>          return _objectCountAttribute;
>      }
> 
> }
> 
> 
> 
> ------------------------------
> 
> Message: 2
> Date: Tue, 1 Feb 2005 12:48:57 +1100
> From: Marek Wawrzyczny <[email protected]>
> Subject: Wrong mailing list, please ignore [Was: Fetching record
> counts.]
> To: Marek Wawrzyczny <[email protected]>
> Cc: [email protected]
> Message-ID: <[email protected]>
> Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed
> 
> Sorry, wrong mailing list please ignore.
> 
> On 01/02/2005, at 12:42, Marek Wawrzyczny wrote:
> 
>> Hi all,
>> 
>> A long time ago I came across Eric Noyau's famous BugTracker, and the
>> useful FetchCounting class. Since then we used something similar to
>> perform counts in our  application, however recently it has become the
>> source of a problem. The source is at the end of the file.
>> 
>> I have to admit, I don't fully understand how it works, but
>> essentially it appears that the target entity is retrieved from the
>> fetch specification. Then a additional "count" attribute is added to
>> the model to perform the count.
>> 
>> There are two problems with that solution we have encountered, the
>> first one results in the following exception:
>> 
>> "Exception while trying to save the EOEditingContext during  the
>> processing of transaction... Stack trace:
>> java.lang.IllegalArgumentException: addAttribute: duplicated attribute
>> name: p_objectCountAttribute
>> at com.webobjects.eoaccess.EOEntity.addAttribute(EOEntity.java:2153)
>> at  
>> ish.common.webobjects.utilities.EOFetchCounting.objectCountWithFetchSpe
>> cification(EOFetchCounting.java:61)
>>     <...>"
>> 
>> I believe that this is caused due to the variable
>> "_objectCountAttribute" being static. I think that two different
>> threads are attempting to perform the fetch count 'simultaneously' on
>> the same entity. One has already added the "count" attribute when the
>> other attempts to do this again.
>> 
>> The second exception we get is:
>> 
>> "java.lang.IllegalArgumentException: addAttribute: attribute has a
>> different entity
>> at com.webobjects.eoaccess.EOEntity.addAttribute(EOEntity.java:2149)
>> at  
>> ish.common.webobjects.utilities.EOFetchCounting.objectCountWithFetchSpe
>> cification(EOFetchCounting.java:61)
>>     <...>"
>> 
>> Here I believe two threads are attempting to perform fetch counts on
>> different entities. Since the static "_objectCountAttribute" can only
>> be linked to one entity at a time, we get the exception when the
>> second thread attempts to add the attribute before the first thread
>> had the opportunity to remove it from its entity.
>> 
>> This is actually where I am stuck. I don't understand the EOModel and
>> EOAttribute mechanism very well. One solution I tried was to add the
>> count attribute permanently, that crashed the application. So I tried
>> creating the attributes on the fly and removing them once finished
>> this worked. However, it doesn't appear I can make this thread-safe
>> since there is no locking mechanism on the EOModel (I think this is
>> why Eric's solution used a static var) and I cannot easily test this
>> concept under duress (when the exceptions actually start occurring).
>> 
>> Can anyone point me in the right direction on this?
>> 
>> 
>> Marek Wawrzyczny
>> 
>> software engineer
>> -------------------------->
>> ish group pty ltd
>> http://www.ish.com.au
>> 7 Darghan St Glebe 2037 Australia
>> phone +61 2 9660 1400   fax +61 2 9660 7400
>> 
>> <<< Code follows >>>
>> 
>> 
>> package ish.common.webobjects.utilities;
>> 
>> 
>> import com.webobjects.foundation.*;
>> import com.webobjects.eocontrol.*;
>> import com.webobjects.eoaccess.*;
>> 
>> 
>> /**
>>  * <p>This class impements methods that allow us to count the number of
>>  * rows for a user defined fetch specification.</p>
>>  *
>>  * <p>The count is performed directly on the database source without
>> having to load
>>  * them into memory.</p>
>>  *
>>  * <p>Original code by Eric Noyau. This class has been taken from
>> Eric's Bugtracker application.</p>
>>  *
>>  * @author Eric Noyau
>>  * @author Marek Wawrzyczny
>>  * @version 1.1
>>  */
>> 
>> public class EOFetchCounting extends Object {
>> 
>>     private static EOAttribute _objectCountAttribute = null;
>> 
>> 
>> /**
>>      * <p>Returns the number of rows metching the fetch
>> specifivation.</p>
>>      *
>>      * @param editingContext - editing context to perform the fetch in
>>      * @param fetchSpecification - the fetch specification
>>      */
>>     public static Number objectCountWithFetchSpecification(
>> EOEditingContext editingContext,
>> EOFetchSpecification fetchSpecification) {
>> 
>>         if (fetchSpecification != null) {
>>             EOFetchSpecification rawFetchspecification;
>> 
>>             try {
>>                 rawFetchspecification =
>> (EOFetchSpecification)fetchSpecification.clone();
>>             } catch (Exception e) {
>>                 System.out.println("\nException in
>> objectCountWithFetchSpecification :\n"+e);
>>                 return null;
>>             }
>> 
>>             EOEntity entity =
>> EOModelGroup.defaultGroup().entityNamed(rawFetchspecification.entityNam
>> e());
>>             EOQualifier schemaBasedQualifier =
>> entity.schemaBasedQualifier(rawFetchspecification.qualifier());
>>             EOAttribute attribute =
>> EOFetchCounting.objectCountAttribute();
>>             NSArray results = null;
>>             entity.addAttribute(attribute);
>> 
>>             // Fix to ensure that fetch counting does not trip the
>> site when
>>             // the fetch fails for some reason
>>             try {
>>                 
>> rawFetchspecification.setQualifier(schemaBasedQualifier);
>>                 rawFetchspecification.setRawRowKeyPaths(new
>> NSArray(attribute.name()));
>>                 results =
>> editingContext.objectsWithFetchSpecification(rawFetchspecification);
>>             } finally {
>>                 // IMPORTANT!!!
>>                 // This needs to run every time, exception or not
>>                 entity.removeAttribute(attribute);
>>             }
>> 
>>             if ((results != null) && (results.count() == 1)) {
>>                 NSDictionary row = (NSDictionary) results.lastObject();
>>                 return (Number)row.objectForKey(attribute.name());
>>             }
>>         }
>> 
>>         return null;
>>     }
>> 
>>     /**
>>      * Returns the number of rows metching the fetch specifivation.
>>      *
>>      * @param editingContext - editing context to perform the fetch in
>>      * @param entityName - the entity to perform the count on
>>      * @param fetchSpecification - the fetch specification
>>      * @param bindings - the fetch bindings
>>      */
>>     public static Number objectCountWithFetchSpecificationAndBindings(
>> EOEditingContext editingContext,
>> String entityName,
>> String fetchSpecName,
>> NSDictionary bindings) {
>> 
>>         EOModelGroup modelGroup = EOModelGroup.defaultGroup();
>>         EOFetchSpecification unboundFetchSpec;
>>         EOFetchSpecification boundFetchSpec;
>>         unboundFetchSpec =
>> modelGroup.fetchSpecificationNamed(fetchSpecName, entityName);
>>         if (unboundFetchSpec == null) {
>>             return null;
>>         }
>>         boundFetchSpec =
>> unboundFetchSpec.fetchSpecificationWithQualifierBindings(bindings);
>>         return objectCountWithFetchSpecification(editingContext,
>> boundFetchSpec);
>>     }
>> 
>>     /**
>>      * <p>Private.</p>
>>      */
>>     private static EOAttribute objectCountAttribute() {
>> 
>>         if ( _objectCountAttribute == null ) {
>>             _objectCountAttribute = new EOAttribute();
>>             _objectCountAttribute.setName("p_objectCountAttribute");
>>              
>> _objectCountAttribute.setColumnName("p_objectCountAttribute");
>>             _objectCountAttribute.setClassName("Number");
>>             _objectCountAttribute.setValueType("i");
>>             _objectCountAttribute.setReadFormat("count(*)");
>>         }
>> 
>>         return _objectCountAttribute;
>>     }
>> 
>> }
>> 
>> _______________________________________________
>> Do not post admin requests to the list. They will be ignored.
>> Webobjects-deploy mailing list      ([email protected])
>> Help/Unsubscribe/Update your Subscription:
>> http://lists.apple.com/mailman/options/webobjects-deploy/
>> marek%40ish.com.au
>> 
>> This email sent to [email protected]
>> 
> 
> Marek Wawrzyczny
> 
> software engineer
> -------------------------->
> ish group pty ltd
> http://www.ish.com.au
> 7 Darghan St Glebe 2037 Australia
> phone +61 2 9660 1400   fax +61 2 9660 7400
> 
> 
> 
> ------------------------------
> 
> _______________________________________________
> Webobjects-deploy mailing list
> [email protected]
> http://lists.apple.com/mailman/listinfo/webobjects-deploy
> 
> End of Webobjects-deploy Digest, Vol 2, Issue 16
> ************************************************
>