Wiki source code of EOF-Using EOF-Problems

Last modified by Pascal Robert on 2007/09/03 14:06

Show last authors
1 = Problems =
2
3 This section describes some problems and bugs that sometimes occur when using //Enterprise Objects Framework//.
4
5 == EOF fails to initialize models when not specifically ordered ==
6
7 **Authors:** Francis Labrie
8
9 **Affected products:** //WebObjects// 5.2.x, 5.3.x
10
11 **Bug reference:** rdar:~/~/4571773
12
13 === Problem: ===
14
15 Sometimes when having several data models using shared objects in a //WebObjects// application, models load, initialization and connection simply fail with strange and unexpected exceptions. Typical exceptions are:
16
17 * {{code language="none"}}java.lang.IllegalStateException: registeredDatabaseContextForModel() Cannot register the database context for the model{{/code}}//<Model name>//
18 {{code language="none"}}at com.webobjects.eoaccess.EODatabaseContext.registeredDatabaseContextForModel(EODatabaseContext.java:1145){{/code}}
19
20 ...
21
22 * {{code language="none"}}java.lang.IllegalStateException: addOrderByAttributeOrdering: attempt to generate SQL for com.webobjects.eocontrol.EOSortOrdering <class com.webobjects.eocontrol.EOSortOrdering({{/code}}//<Attribute Name>// {{code language="none"}}compareAscending)> failed because attribute identified by key '{{/code}}//<Attribute Name>//{{code language="none"}}' was not reachable from from entity '{{/code}}//<Entity Name>//{{code language="none"}}'{{/code}}
23 {{code language="none"}}at com.webobjects.eoaccess.EOSQLExpression.addOrderByAttributeOrdering(EOSQLExpression.java:1803){{/code}}
24 ...
25
26 * //etc.//
27
28 I saw several report of this bug in various mailing list, but no one leads to a right solution or a good explanation:
29
30 [[http:~~/~~/lists.apple.com/archives/webobjects-dev/2005/Aug/msg00295.html>>url:http://lists.apple.com/archives/webobjects-dev/2005/Aug/msg00295.html||shape="rect"]]
31 [[http:~~/~~/www.wodeveloper.com/omniLists/webobjects-dev/2004/September/msg00255.html>>url:http://www.wodeveloper.com/omniLists/webobjects-dev/2004/September/msg00255.html||shape="rect"]]
32
33 === Solution: ===
34
35 I've finally found that this problem is related to the models load and initialization order. Most of the time, EOF is able to initialize a group of models flawlessly. But in some circumstances, it just fails.
36
37 The best fix would be to make EOF dynamically analyse models groups, building a graph of dependancy with all entities for each group and ordering the models and the entities initializations according to this graph. But a such solution is a little bit more complex and should typically be integrated directly into the EOAccess layer.
38
39 To work around this bug with a simpler solution, you can add in the {{code language="none"}}userInfo{{/code}} dictionary of each model the {{code language="none"}}priority{{/code}} key assigned to a value of four digit, example: {{code language="none"}}0100{{/code}}, {{code language="none"}}0500{{/code}}, {{code language="none"}}2000{{/code}}, //etc.// You must use priority values with the same number of digit, because these will be converted to strings, and if you set a priority of {{code language="none"}}500{{/code}}, the string value will be considered as higher than a priority of {{code language="none"}}1000{{/code}}.
40
41 Then create a static method that perform an {{code language="none"}}assertConnectionDictionaryIsValid(){{/code}} with each model of the group sorted by priority:
42
43 {{code}}
44
45 private static final NSArray _PriorityDescendingModelSortOrdering = new NSArray(new Object[] {
46 EOSortOrdering.sortOrderingWithKey("userInfo.priority", EOSortOrdering.CompareDescending),
47 EOSortOrdering.sortOrderingWithKey("name", EOSortOrdering.CompareAscending)
48 });
49
50 ...
51
52 public static void assertModelGroupConnectionDictionariesAreValid(EOEditingContext editingContext, EOModelGroup modelGroup) {
53 Enumeration models;
54 EOAdaptor adaptor;
55 EODatabaseContext databaseContext;
56 EOModel model;
57
58 // Get models enumerator from default group
59 models = EOSortOrdering.sortedArrayUsingKeyOrderArray(modelGroup.models(),
60 _PriorityDescendingModelSortOrdering).objectEnumerator();
61
62 while(models.hasMoreElements()) {
63 model = (EOModel)models.nextElement();
64 NSLog.debug.appendln(" Connecting " + model.name() + " model, userInfo = " + model.userInfo() + "...");
65 databaseContext = EODatabaseContext.registeredDatabaseContextForModel(model, editingContext);
66 adaptor = databaseContext.adaptorContext().adaptor();
67
68 // Test connection dictionary
69 adaptor.assertConnectionDictionaryIsValid();
70 NSLog.debug.appendln(" The \"" + model.name() + "\" model is connected.");
71 } // while
72 } // assertConnectionDictionariesAreValid
73
74 {{/code}}
75
76 The sort ordering here sort by descending model priority and ascending model name to ensure constancy on sort result.
77
78 You'll have to find the right model order: you can deduce it with logic drawing a dependency graph, or you can find it with tests and errors. Typically, when an exception has above is thrown, it's because the model initialization was done too late. I usually set priority to framework models from {{code language="none"}}1000{{/code}} (low) to {{code language="none"}}9000{{/code}} (high), and application models from {{code language="none"}}0100{{/code}} (low) to {{code language="none"}}0900{{/code}} (high).
79
80 === Exception: ===
81
82 For some cases, this solution still does't help (see [[this message>>url:http://lists.apple.com/archives/Webobjects-dev/2006/Oct/msg00000.html||shape="rect"]]). I suspect the entities ordering in model to be the problem (see [[#EOF fails to fetch or save entities when not correctly ordered in model>>doc:||anchor="EOF fails to fetch or save entities when not correctly ordered in model"]] below). If it's still not the case, you can try to use the [[ERXSharedEOLoader>>url:http://wonder.cvs.sourceforge.net/wonder/Wonder/Common/Frameworks/ERExtensions/Sources/er/extensions/ERXSharedEOLoader.java?revision=1.9&view=markup||shape="rect"]] class in [[Project Wonder>>url:http://wonder.sourceforge.net||shape="rect"]].
83
84 == EOF fails to fetch or save entities when not correctly ordered in model ==
85
86 **Authors:** Francis Labrie
87
88 **Affected products:** //WebObjects// 5.2.x, 5.3.x
89
90 **Bug reference:**
91
92 === Problem: ===
93
94 Sometimes when using inherritance with entities in a data model in a //WebObjects// application, fetching or saving data may simply fails with strange and unexpected exceptions. Typical exception is:
95
96 * {{code language="none"}}com.webobjects.eoaccess.EOGeneralAdaptorException: sqlStringForKeyValueQualifier: attempt to generate SQL for{{/code}} //<Qualifier Class>// {{code language="none"}}({{/code}}//<Qualifier Expression>//{{code language="none"}}) failed because attribute identified by key 'NeededByEOF0' was not reachable from from entity{{/code}} //<Entity Name>//
97 {{code language="none"}}at com.webobjects.eoaccess.EODatabaseContext._exceptionWithDatabaseContextInformationAdded(EODatabaseContext.java:4685){{/code}}
98 ...
99
100 * //etc.//
101
102 === Solution: ===
103
104 Typically, this kind of error occurs when the parent entity is in an another model which was initialized after the current entity model one (see [[#EOF fails to initialize models when not specifically ordered>>doc:||anchor="EOF fails to initialize models when not specifically ordered"]] above) or when the parent entity is coming after the current entity in the alphabetically ordered list of entities of the current model. To illustrate the latter case: if your abstract parent entity name is "Flower" and you are fetching the concrete sub-entity "Anemone" while both entities are part of the same model, you can get this kind of exception on the first "Anemone" fetch.
105
106 To avoid this exception, simply edit the "index.eomodeld" file in a text editor and reorder the entities references in the array, putting parent entities above sub-entities. But you should then take care with the //EOModeler//: you'll have to reorder these entities references each time you modify and save the model.
107
108 == New sub-entity insertion fails because primary key is null ==
109
110 **Authors:** initially reported by Chuck Hill
111
112 **Affected products:** //WebObjects// 5.2.x, 5.3.x
113
114 **Bug reference:**
115
116 === Problem: ===
117
118 When a sub-entity have a parent entity with a relationship set to //propagate primary key//, any new sub-entity insertion when saving changes from an editing context will throw an integrity violation exception because the primary key column is set to {{code language="none"}}null{{/code}}.
119
120 === Solution: ===
121
122 To avoid this bug, uncheck the //Propagate primary key// relationship property of the parent entity. Unfortunately, if the parent entity is not abstract, this solution will not be applicable: you'll probably have to modify the relationship modeling itself.
123
124 == Strange Locking Behavior ==
125
126 It would appear that there is, in our opinion, some bugs related to optimistic locking within a single EOF stack. Essentially what it boils down to is that it appears that the update database operation that is created as a result of a call to .saveChanges() is backed by the EODatabaseContext snapshot and NOT the "working" snapshot inside in the EO in the editing context it came from. What this means is that while changes are not merged until you .unlock() and .lock() under normal circumstances, because the underlying snapshot that EOF diffs your changes against on save is the DBC snapshot, it's effectively inadvertently "merged" on commit. That is to say that if another EC makes changes and saves, then you make different changes and save, you will blow away their changes with no sign of an optimistic locking exception because your snapshot IS their snapshot now (meaning, it looks like just you are overwriting their changes, versus the reality of the situation that you are actually conflicting with their changes). After discussing this some, we believe that if the update operation used a version of the EO's backing snapshot instead that these weird behaviors would be fixed and it would behave exactly like a normal conflicting update if you were in two EOF stacks. The current behavior smells of bug, but I'm curious if anyone a dissenting opinion on the topic. It's certainly really complicated and nasty down in that code, so it's possible there's some crazy justifiable reason for it.
127
128 Here are two diagrams of examples. Left side is EC 1, right side is EC 2, purple is the state of the EO in EC1 at various points, yellow is the state of the same EO in EC2 at various points.
129
130 Here's the "blow-away-other-changes-in-the-EO" workflow:
131 [[image:attach:Picture 3.png]]
132
133 Here's the "no optimistic lock exception" example:
134 [[image:attach:Picture 4.png]]