Pinaki,
Our test team wanted to test the  interaction between the annotation of fetch group and the declaration of the fetch type on the attributes as well as the fetch group arcitechure. Yes, they may not be the real examples in a business enviornment. However, they served a good understanding of fetch group architecture if the test results are correct.
 
After reviewed your comments,  I modified my test case to fit into the openjpa test suite. In addition, I also took your suggestion to move the em.findEmployee to a separate method to avoid some side effort. However, the test result did not match with my interpretation of the FetchGroup architecture. I like to verify the following interpretation first before debugging the problem.
 
1) Use the annotation to define the custom fetchGroup on an entity will not be automatically active during the runtime. You can activate the FetchGroup thru the addFetchGroup API in the application.
2) @LoadFetchGroup does not relate to the FetchGroup. If field a has @LoadFetchGroup X, when field a is loaded, it also loads all fields included in fetchGroup X.
3) If there is a fetch group defined in the persistence.xml file, this will be the default fetch group along with the original "default" fetch group. Therefore, the global configuration will have the original default fetch group + any fetch groups that are defined in the persistence.xml file. .All the attributes are defined in these default fetch groups will be eagerly loaded at runtime.
4) resetFetchGroup will reset the current active FetchGroup to global configuration that is specified in #3.
5) Nesting fetch group  ( need confirmation here): when a fetch group X is added to a fetch plan during the runtime, its nested fetch groups should also be activated in runtime.
6) When a fetch group X is added to a fetch plan during the runtime, only this fetch group X and its nested fetch groups are activated (see #5). Other fetch groups will not be activiated even though those fetch groups have the same attribute members as the fetch group X.

Please verify the above interpretation. The test result showed #2, #3, #5 and #6 were incorrect.
I also attached the testcases here: one without the property and one with the property. You can add the following line in the persistence.xml file and test with TestFetchGroupWithProperty:

<property name="openjpa.FetchGroups" value="default,AggregateEmployeeFetchGroup3" />

Thanks,
Teresa
 
On 9/4/07, Pinaki Poddar <ppoddar@bea.com> wrote:
Teresa,

Few notes:
1. The entity classes had annotated certain fields Fetch.LAZY and test
code is verifying which fields are fetched under different fetch
configuration. Annotating a field x which otherwise would be in default
fetch group (say String FGEmployee.rating in your example) with
Fecth.LAZY will keep field x out of default fetch group.
So if only default fetch group is active (for example, after a
resetFetchGroups() call), then em.find(FGEmployee.class, id) will fetch
a Employee but not 'rating' field. Employee.rating will only be fetched
if user code calls emp.getRating().

2. But if the test code does something as follows within an active
transaction:
  boolean isRatingFetched = (emp.getRating()!=null);

  then a Schrodinger's principle becomes active i.e. due to the
observation process itself, the observed gets perturbed. The result of
emp.getAddress() will *now* fetch the LAZY 'rating' field and
isRatingFetched will become true. However, em.find(FGEmployee.class, id)
may not have fetched 'rating' which is actually what the test is trying
to verify.
Some of the attached test code is impacted by this effect.
The safe way to eliminate such side-effect is to commit the transaction
and close (not clear) the entity manager *before* starting to check
which fields are fetched as a result of a find() or query result.

3. I would suggest that capture the oft-repeated code patterns in the
Test case of finding an Employee under different fetch configuration to
put in a single method like (this one ensures that the returned Employee
will not further fetch its state as a side-effect of get() calls):

   private FGEmployee findEmployee(Object id, boolean reset,
String...fetchGroups) {
       EntityManager em = emf.createEntityManager();

     OpenJPAEntityManager oem = OpenJPAPersistence.cast(em);
       oem.getTransaction().begin();
       if (reset) {
               oem.getFetchPlan ().resetFetchGroups();
               assertEquals(1,
oem.getFetchPlan().getFetchGroups().size());
               assertEquals("[default]",
Arrays.toString(oem.getFetchPlan().getFetchGroups().toArray()));
       }
       if (fetchGroups!=null)
               for (String fg:fetchGroups)
                       oem.getFetchPlan().addFetchGroup(fg);
       FGEmployee emp = oem.find(FGEmployee.class, id);
       oem.getTransaction().commit();
       oem.close();
       return emp;
   }

4. I would also suggest to use
TestCase.assertNull(emp.getRating()) or assertNotNull(emp.getRating())
wherever System.out.pritln ("....") is used to verify manually.
Because without any asserts, Junit Tests think they pass!

5. Another suggestion will be *not* to mix compile-time FetchType.LAZY
and run-time fetch plans in the tests at least for initial
verifications.
So keeping the fields without ant FecthType annotations and control what
is fetched only by run-time manipulation of fetch plans will expose the
functioning (and any possible bug) associated with fetch groups.
In a later phase, the tests can explore how mixing compile-time
FetchType.LAZY and run-time fetch plans change the behavior.




Pinaki Poddar
972.834.2865


>-----Original Message-----
>From: Teresa Kan [mailto:tckan1@gmail.com]
>Sent: Tuesday, September 04, 2007 9:26 AM
>To: dev@openjpa.apache.org
>Subject: Re: FetchGroup and FetchAttribute question
>
>Pinaki,
>I used the debugger to check that the FetchGroup was added
>when the application explicitly added that FetchGroup.
>I attached the testcase in this note. Please noted that I did
>not use the Assert to verify the result because I'm not sure
>about the outcome. I used the println to print out the result instead.
>
>Thanks,
>Teresa
>
>
>On 8/31/07, Pinaki Poddar < ppoddar@bea.com> wrote:
>
>       Hi,
>       Few comments in-line....
>
>       What is the mechanics to cofirm if a field is loaded as
>a result of a
>       API call?
>
>       Can you post a test case for us to investigate further?
>
>
>       Pinaki Poddar
>       972.834.2865
>
>
>       >-----Original Message-----
>       >From: Teresa Kan [mailto: tckan1@gmail.com
><mailto:tckan1@gmail.com> ]
>       >Sent: Friday, August 31, 2007 11:46 AM
>       >To: dev
>       >Subject: Re: FetchGroup and FetchAttribute question
>       >
>       >In addition to previous question, I have question about the
>       >lifecycle of a FetchGroup and need some clarifications on the
>       >expected behavior. Please verify each step result is  a
>       >correct behavior. If they are correct, then we need to
>       >document those behavior in the javadoc and openjpa manual:
>       >
>       >Use the following example,
>       >
>       >@FetchGroups({
>       >   @FetchGroup(name="AddressFetchGroup", attributes=
>       >{@FetchAttribute(name="address")} ),
>       >   @FetchGroup(name="RatingFetchGroup", attributes=
>       >{@FetchAttribute(name="rating")}),
>       >@FetchGroup(name="ManagerFetchGroup1A", attributes=
>       >{@FetchAttribute(name= "manager" , recursionDepth=1)} )
>       >})
>       >public class FGEmployee{
>       >    @Id
>       >    private int id;
>       >
>       >    @OneToOne(fetch=FetchType.LAZY)
>       >    private FGAddress address;
>       >
>       >    @Basic(fetch=FetchType.LAZY)
>       >    @LoadFetchGroup("AddressFetchGroup")
>       >    private String rating;
>       >
>       >    @ManyToOne(fetch=FetchType.LAZY)
>       >    private FGManager manager;
>       >
>       >..
>       >}
>       >
>       >Test case:
>       >1.         oem.persist(employee);
>       >==> What happen to 3 fetchGroups? Are they active at this time?
>       >From the debugger, the fetchGroup was set to "default". At
>       >this time, I can't tell whether the default means those 3
>       >fetchGroups or the default w/o any custom FetchGroups? If I
>       >did not reset the FetchGroup and  did not explicitly add the
>       >fetchGroups, both address and rating are eagerly loaded.
>       >So it implies that all 3 fetchGroup are active when the
>       >employee is persisted.
>
>       The custome fetch groups are not active under this
>configuration.
>       How are you confirming that "both address and rating
>are eagerly loaded"
>       -- looking at the SQL issued, by reflectively looking
>into the instance?
>       FetchGroups are not relevant during persist() operation.
>       In a clean cache, undet the 'default' configuration,
>for a find() or
>       query, rating will be fetched and address will not.
>
>
>       >==> What happen if there is no LoadFetchGroup annotated on
>       >rating? Will the AddressFetchGroup be active ?
>       >From the test result, this is true.. Then why we need to use
>       >LoadFetchGroup explicitly?
>
>       If field a has a LoadFetchGropu X -- it means "if field
>a is loaded also
>       load all fields included in fecthgroup X".
>LoadFetchGroup does not
>       control which fetch group is active.
>
>
>       >
>       >2.          oem.getFetchPlan().resetFetchGroups();
>       >              oem.clean();
>       >==> What is the expected behavior in resetFetchGroups()?
>       >According to the
>       >javadoc:
>       >Resets the set of fetch groups to the list in the
>global configuration.
>       >What does the "global configuration" mean? The default fetch
>       >group w/o custom fetch group? or the one that defined thru
>       >annotation? or the one in the persistence.xml file?
>       >
>
>       'global configuration' implies the fetch groups specified in
>       persistence.xml via 'openjpa.FetchGroups' property.
>
>       >I assume that 3 fetchGroups are not active. From the debugger,
>       >it showed the "default" which I guessed the default w/o custom
>       >fetch groups..
>       >How about the LoadFetchGroup? it seems to me that this fetch
>       >group was deactive too. Is this an expected behavior?
>       >From the test result, both address and rating are NOT
>eargly loaded.
>       >
>
>       LoadFetchGroup does not control which fetch group is active.
>
>       >
>       >3.
>oem.getFetchPlan().addFetchGroups("RatingFetchGroup");
>       >==>  What is the expected behavior? The RatingFetchGroup is
>       >added to the fetchPlan. From the debugger, I saw both default
>       >and RatingFetchGroup.
>       >The test result showed the rating was eagerly loaded but not
>       >the address. It seems to me that the resetFetchGroup() disable
>       >the AddressFetchGroup even though it was specified in the
>       >rating thru LoadFetchGroup.  Is this an expected behavior?
>       >
>       >
>       >
>       >4.            FGEmployee emp = oem.find(FGEmployee.class, 1);
>       >==> What happen to the Address and Rating fields?
>       >  a) if Rating does not have the LoadFetchGroup annotation,
>       >and no resetFetchGroup call:
>       >  ===> both Address and Rating are eagerly loaded.
>       > b) if Rating has the LoadFetchGroup annotation and no
>       >resetFetchGroup call:
>       > ===> same as a)
>       > c) Regardless of  the LoadFetchGroup, if resetFetchGroup is
>       >called and  no addFetchGroup is called:
>       > ==> both Address and Rating are not eagerly loaded.
>       > d) If resetFetchGroup is called and addFetchGroup on
>       >RatingFetchGroup is
>       >called:
>       > ==> Address is LAZY and rating is eager.
>       > e) if resetFetchGropu is called and addFetchGroup on both
>       >Address and Rating fetch groups:
>       > ==> both Address and Rating are eagerly loaded.
>       >
>       >5) one more question, if I defined a FetchGroup within a
>       >FetchGroup, for example, @FetchGroups({
>       >@FetchGroup(name="AggregateEmployeeFetchGroup1",
>       >                attributes= {
>       >                    @FetchAttribute(name="dept"),
>       >                    @FetchAttribute(name="address"),
>       >                    @FetchAttribute(name="manager",
>recursionDepth=1)
>       >                } ),
>       > @FetchGroup(name="AggregateEmployeeFetchGroup2",
>       >fetchGroups={"AggregateEmployeeFetchGroup1"} ), } ===> if I
>       >reset the fetch group, and only add the
>       >AggregateEmployeeFetchGroup2. Nothing will happen because the
>       >AggregateEmployeeFetchGroup1 is deactivated by
>       >resetFetchGroup(). Unless I add both fetchGroup in runtime,
>       >none of the dept, address, manager are eagerly loaded. Is this
>       >an expected behavior?
>       >
>       >Please verify the above behaviors.. I can't tell the lifecycle
>       >of the FetchGroup that associated with LoadFetchGroup and
>       >resetFetchGroup..
>       >
>       >Thanks,
>       >Teresa
>       >
>       >
>       >
>       >
>       >
>       >
>       >
>       >On 8/30/07, Teresa Kan <tckan1@gmail.com> wrote:
>       >>
>       >> If I have a fetchAttribute manager which is included
>in multiple
>       >> FetchGroups. For example,
>       >>
>       >> @FetchGroup(name="ManagerFetchGroup1A",
>       >>
>       >> attributes= {
>       >> @FetchAttribute(name="manager" , recursionDepth=1)} ),
>       >>
>       >> @FetchGroup(name="ManagerFetchGroup1B",
>       >>
>       >> attributes= {
>       >> @FetchAttribute(name="manager" , recursionDepth=-1)} ),
>       >>
>       >> @FetchGroup(name="ManagerFetchGroup2",
>       >>
>       >> attributes= {
>       >> @FetchAttribute(name="manager" , recursionDepth=2)} ),
>       >>
>       >> In my test case, I did the following:
>       >>
>       >> oem.getFetchPlan().resetFetchGroups();  ===> reset to default
>       >>
>       >> oem.clear();
>       >>
>       >> oem.getFetchPlan().addFetchGroups(
>       >> "ManagerFetchGroup1A");
>       >>
>       >> I found out that openjpa will add all 3 FetchGroups back to
>       >the fetch
>       >> plan. My guess was that the manager was associated with 3
>       >FetchGroups.
>       >> The recursionDepth will be set to -1. Is this an expected
>       >behavior? I
>       >> can't find any statement from the openjpa manual.
>Please clarifiy!
>       >>
>       >> Thanks,
>       >>
>       >> Teresa
>       >>
>       >>
>       >>
>       >>
>       >>
>       >>
>       >>
>       >>
>       >>
>       >>
>       >>
>       >
>
>       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.
>
>
>
>

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.