5 Replies Latest reply on Jun 22, 2007 10:22 AM by jfrankman

    Complex Search Results - return object identifiers instead o

      In general, when you have a session bean that performs a search is it sometimes better to return object identifiers instead of the entire objects themselves?

      I have a search page where a user can enter various criteria to get a search results. Once the search results are returned, the user can click on a record to go to a detail page. In most seam examples I have seen, this is done with a session bean that returns a list of objects and loads them on the search results page and subsequently gets injected into the detail page when the user selects a row in the search results.

      However, in the case of a complex/expensive query does it ever make sense to merely return a list of object identifiers rather than the objects themselves? What this would mean is that after the results were returned, and the user selected a record, the object identifier would be injected into a lookup method on a session bean that would then retreive the entire object rather than having the object being injected directly from the search results page. (I hope I am makes sense with this)

      (I can supply more code and examples, but I didn't want to get into the nitty gritty unless I had to. )

      I understand that for simple searches returning objects and then injecting the objects directly into the the detail page would be better, but in the cases of complex queries or cases where you need to pre fetch a fairly large object graph on the detail page, it makes sense to me just to return an object identifier rather than the objects themselves. But I am still quite new at all of this, so I am looking for feedback from more experienced (or smarter) persons.

      Any feedback is appreciated. Thanks.

        • 1. Re: Complex Search Results - return object identifiers inste
          twocoasttb

          I'm no expert, but this makes sense to me. I'm planning on doing something similar in my application when selecting sets objects with a deep object graph for display (and selection). Purists will no doubt howl, but I plan, in some cases, to create views to generate search results. A 'flat proxy POJO' (I don't know what else to call it) would be defined for each view. And from that proxy object, I'll get the id of the object the user is actually interested in, and go fetch it.

          I haven't benchmarked any of this yet, but I expect the application would do much less work. Plus, I get more control over the SQL actually executed during the search.

          • 2. Re: Complex Search Results - return object identifiers inste
            pmuir

            Not really. We have this wonderful thing called lazy fetching which makes the kind of pre-optimization you are planning largely useless. If you want to do things this way, why not just write your own ORM rather than use an existing one?

            • 3. Re: Complex Search Results - return object identifiers inste

              I agree that lazy instantiation is the best way to go, but my problem with the lazy instantiation is that I have trouble keeping my objects in the session. My seam action classes call my business layer to get all objects:

              i.e. List clients=clientService.findByLastName("Doe");

              This works fine to display the search results, but when I click a detail row to go to the detail page I get lazy initialization errors:

              client.getPolicies(); <-- produces lazy initialization error.

              I think the problem is that the call to the entity manager is buried in my DAO layer and is not in the action itself. In other words, my action calls the business layer which in turn calls the DAO layer to get the object. Because the EntityManager is not in the action I get lazy initialization errors, is this correct? Am I going about this all wrong?

              I know there must be a way to do this, but others have complained about this problem as well: http://www.jboss.com/index.html?module=bb&op=viewtopic&t=62275

              I cannot quite understand how to keep the object in the session between pages I keep getting LazyInitialization errors on all subsequent pages. What am I doing wrong?

              • 4. Re: Complex Search Results - return object identifiers inste
                pmuir

                Are you using a long running conversation with a conversation scoped (aka seam managed) persistence context?

                • 5. Re: Complex Search Results - return object identifiers inste

                  My entity bean has session scope:

                  @Table(name="FBCLIENT",schema="DB2ADMIN")
                  @Name("client")
                  @Scope(ScopeType.SESSION)
                  public class ClientVO implements Serializable
                  {
                   private static final long serialVersionUID = 2285612284592204149L;
                  
                   private Long id;
                   private String notes;
                   private String clientType;
                   private String memberNumber;
                   private Set<ClientLocationVO> entityLocations = new HashSet<ClientLocationVO>();
                   private Set<PolicyVO> policies = new HashSet<PolicyVO>();
                   private String search;
                   private DrivingDistance drivingDistance;
                   private String homePhone;
                   private String workPhone;
                   private String cellPhone;
                   private String pagerNo;
                   private String email;
                   private ClientVO parentClient;
                   private List<ClientVO> clientMembers=new ArrayList<ClientVO>();
                  
                   /**
                   * @return the childMembers
                   */
                  
                  
                   @OneToMany(mappedBy="parentClient",fetch=FetchType.LAZY)
                   public List<ClientVO> getClientMembers() {
                   return clientMembers;
                   }
                  
                   /**
                   * @return the parentClient
                   */
                  
                   @ManyToOne()
                   @JoinColumn (name="parentclientid" )
                   public ClientVO getParentClient() {
                   return parentClient;
                   }
                  ....


                  When I perform the search I do not use a conversation, just a stateless session bean:

                  @Stateless
                  @Name("search")
                  public class SearchAction implements Search
                  {
                   @In Identity identity;
                  
                   @In private SearchVO searchvo;
                   @In(create=true) private ClientService clientService;
                   @In(create=true) private PolicyService policyService;
                  
                  
                   @In(required=false)
                   private FBWorker worker;
                  
                   @Out(required=false) private PolicyVO policy;
                   public String performNameSearch()
                   {
                  
                   searchResults = policyService.findPolicyHoldersByNameIncludeSubclients(searchvo.getSearchString());
                  
                   searchvo.setSearchResults(searchResults);
                   return "success";
                   }
                  
                  ...


                  When the user clicks the row in the datatable I then try and load the entire object by calling the lookupClientFromSearch method on my ClientAction stateful bean. :

                  <h:commandLink value="#{searchResult.clientVO.fullName}" action="#{clientAction.lookupClientFromSearch}"/>


                  Inside the lookupclientFromSearch I am using a conversation:
                  @Stateful
                  @Name("clientAction")
                  public class ClientActionImpl implements ClientAction
                  {
                   @In(create=true) private ClientService clientService;
                   @In(required=false) @Out(required=false) ClientVO client;
                   @In @Out(required=false) PolicyVO policy;
                   @In(required=false) ClientVO subClient;
                   @In(required=false) MasterSearchResultVO searchResult;
                  
                   @Begin(join=true)
                   public String lookupClientFromSearch() {
                   client=clientService.findClientByIdFetchGraph(searchResult.getClientVO().getId());
                  
                   if (client instanceof PersonVO)
                   {
                   organizationFlag=false;
                   personFlag=true;
                   System.out.println("The Client is a PersonVO");
                  
                  policy.getPolicyHolder();
                   }
                   else if (client instanceof OrganizationVO)
                   {
                   organizationFlag=true;
                   personFlag=false;
                   System.out.println("The Client is a PersonVO");
                   }
                   else
                   {
                   System.out.println("The Client is a only a ClientVO");
                   }
                  
                   return "success";
                   }
                   @End
                  ....