WebObjects/EOF/Modeling/Booleans

Overview edit

There are many way of modeling Boolean in WO.

I like this one as it does not require any specific code and is very readable in the database:

Caution this only works in WO 5.2 and is broken in WO 5.0 to WO 5.1.4

Here is how I do it. I define the column as a Character Varying of 5 so that I can store "true" or "false". In EOModeler I define the Internal Data Type as custom the class as java.lang.Boolean, the factory method as valueOf and the Conversion method as toString and the init argument as NSString. This works well even if it wastes a little space in the database.

To make it easier to use you should define it as a prototype.

Note - this is also discussed in the book "Practical WebObjects"; on page 42.

Jesse Barnum edit

Another way to accomplish this is to define your attribute as a Number with 'c' as the value type in EOModeler. This causes the JDBC adaptor to use the getBoolean() / setBoolean() methods on the ResultSet, so you can use whatever data type you want on the database as long as the JDBC driver supports it.

If you want to write custom accessor methods, you can use Boolean types and EO will automatically do the casting - so this will work:

 public Boolean getAttribute() { return storedValueForKey("attribute"); }
 public void setAttribute(Boolean input) { takeStoredValueForKey(input, "attribute"); }

Jonathan Rochkind edit

Interestingly, in WO 5.2, _regardless_ of how you have set the 'value type' in EOModeler, EOF will sometimes automatically convert any numeric db column to a Boolean value. If you have an attribute called 'someAttribute', and the class for the entity defines a method like "public Boolean someAttribute()", then storedValueForKey("someAttribute") will automatically return a Boolean (whether you like it or not!). If the signature is small-b boolean, this is true too. There may be other cases where it is true---it's entirely undocumented and I just figured it out through experiment.

The algorithm used to convert the numeric data to a Boolean seems to be---if the number is 1, return Boolean(true), otherwise (including null) return Boolean(false). null is never returned by storedValueForKey ("someAttribute") in this situation, even if there was a null in the db. Again, it doesn't seem to matter what the 'value type' in the EOModel is.

Jesse Barnum edit

I'm noticing the exact same thing as Jonathan. However, this 'feature' introduces a problem - the stored snapshot from the database contains the value '1' (I guess the conversion happens after that point), and whenever I save changes to the database, EOF thinks that that attribute has changed from '1' to 'true', and it writes this to the database, even when this is not necessarily appropriate.

Jonathan Rochkind edit

The problem is worse than that. In addition to what Jesse notes, this 'feature' causes some serious problems with EOF, probably related to the stuff Jesse is talking about. Particularly, in some cases EOF will think an attribute _hasn't_ changed even when it has, and not write anything to the db even when it should. The presence of an 'automatically converted attribute' seems to trigger this problem, but the changed properties that EOF will get confused about may occur in OTHER attributes or even relationships! I can not really explain this; I can not even explain under what circumstances it occurs. But I had a situation where a to-one relationship destination was changed, but EOF would not write the changes on saveChanges(). However, removing the 'automatic boolean converted' attributes, making no other changes to the program, made the problem go away. [WO 5.2]

I recommend _avoiding_ the automatic boolean conversion. It causes all sorts of problems. [I filed a request with Apple asking for a way to turn off this automatic boolean conversion, but the engineers said no. I filed my own bug report. Jesse, you should file one about what you note specifically.]

For more description of this bug, see: Weird52EOFBug I know this bug effects 5.2.1; I don't believe it's been fixed in 5.2.2. (written 13 March 2004)

5.2.3 Release Notes edit

Just noticed this in the Release Notes of 5.2.3 http://docs.info.apple.com/article.html?artnum=107873 --- To-one relationship does not update correctly when destination entity has boolean attribute

Apple Reference 3108071

ISSUE: Upon saving changes, the destination entity with boolean attributes does not commit correctly to the database because the snapshot is in an invalid state.

RESOLUTION: In order to resolve this problem, the behavior of a boolean attribute that is defined with a Number value class and value type of 'c' will now return a Boolean value instead of an Integer value.

Mark Gowdy edit

My 'zero effort' approach is as follows: In EOModeler, I have an attribute called 'enabled':

 Name = 'enabled'
 Value Class (Java) = 'Boolean'
 External Type = 'BOOL' (in MySQL it maps to tinyint(1))
 Value Type 'c'

EOModeler complains that it needs 'valueFactoryMethodName' and 'adaptorValueConversionMethodName' for this attribute, but it seems that you can just ignore it.

When I generate my java, I get:

 public Boolean enabled(){ return (Boolean)storedValueForKey("enabled"); }
 public void setEnabled(Boolean v){ takeStoredValueForKey(v, "enabled"); }

My initial tests look promising, but can you guys try it with 5.2.3+ and your reproduceable case to make sure?