Narrowing an initialized proxy, to a proxy of a sub-entity, makes the new narrowed proxy uninitialized. Calling isInitialized() on the new proxy returns false, which causes problems for anything that relies on that method to determine whether an entity has been fetched. One example is prefetching, that will fetch such an entity again, but a more serious example is searching, where results will go missing.

A proxy is narrowed when an entity load occurs for a specific subtype, while a proxy for a supertype already existed for that entity. Searching first executes a query to fetch all the results, and then performs a load for each match, to get the fetched entities from the Hibernate session in the correct order. If such a load narrows a proxy, then the proxy will become uninitialized, and uninitialized proxies are dropped from the result. A minimal example follows:

application narrowproxy

entity Root {
  a -> A
}

entity A {
  name :: String (searchable)
}

entity B : A {
}

var r : Root := Root { a := B { name := "I am a B" } };

page root() {
  var matches : List<A>;
  init {
    log(r); // Causes r to be fetched, which creates a proxy of type A for property a, that actually contains a B.
    var searchr := search A matching name: +"I am a B";
    matches := searchr.results(); // Executes a query that fetches B and initializes the proxy of type A that was previously created.
                                  // The following load causes the proxy of type A to be narrowed to type B, causing the only match to be dropped from the result.
  }
  output(matches) // As a result this shows nothing
}

This can be fixed by forcing the new narrowed proxy to reuse the underlying object of the first proxy whenever possible.

Submitted by Christoffer Gersen on 11 October 2012 at 13:23

On 11 October 2012 at 13:24 Christoffer Gersen closed this issue.

On 9 November 2012 at 17:50 Christoffer Gersen tagged 1.3.0

Log in to post comments