// 
//     Licensed to the Apache Software Foundation (ASF) under one
//     or more contributor license agreements.  See the NOTICE file
//     distributed with this work for additional information
//     regarding copyright ownership.  The ASF licenses this file
//     to you under the Apache License, Version 2.0 (the
//     "License"); you may not use this file except in compliance
//     with the License.  You may obtain a copy of the License at
// 
//       http://www.apache.org/licenses/LICENSE-2.0
// 
//     Unless required by applicable law or agreed to in writing,
//     software distributed under the License is distributed on an
//     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//     KIND, either express or implied.  See the License for the
//     specific language governing permissions and limitations
//     under the License.
//

= DevFaqLookupLazyLoad
:jbake-type: wiki
:jbake-tags: wiki, devfaq, needsreview
:jbake-status: published
:keywords: Apache NetBeans wiki DevFaqLookupLazyLoad
:description: Apache NetBeans wiki DevFaqLookupLazyLoad
:toc: left
:toc-title:
:syntax: true

==== How do I lazy-load an item in the Lookup?

A node is typically used to represent some business object and it's a common idiom to place that business object in the node's lookup so that, for example, a context-sensitive action can operate on it.  Sometimes fully initializing that business object can involve an expensive operation that would be wasted effort if the user never invoked the action that used it anyway.  

So how can you defer loading or initializing the business object until it is truly needed?

There are probably several ways, but two common ones are:

==== Override the `beforeLookup(Lookup.Template<?> template)` method

If you are using the `AbstractLookup` class to create the lookup, you can override the `beforeLookup(Lookup.Template<?> template)`.  By doing this, you will be notified just before a lookup query is processed and you could check to see if the template would match the objects for which you've deferred loading, giving you an opportunity to load them now and add them to the `InstanceContent` used by the `AbstractLookup`.

==== Use `InstanceContent.Convertor` to create a placeholder object

The `InstanceContent.Convertor` class can be registered in an `AbstractLookup` such that it provides a typesafe placeholder until the actual object type is requested, and at that point, the convertor can create and return the actual object.

Consider the following example in which you have a `Token` class which represents a database record ID and a business object class `AnExpensiveClass` which will be populated from the database based on the supplied token's ID.  

[source,java]
----

public final class Token {
      
    private final long id;

    public Token(long id) {
        this.id = id;
    }

    public long getId() {
       return id;
    }
}

----

Now we will write a converter.  Until the first time something calls `theLookup.lookup(AnExpensiveClass.class)`, only our quick-to-create `Token` object is in memory.  On the first such lookup call, the following code is run:

[source,java]
----

public class LazyLoadingDelegate implements InstanceContent.Convertor<Token, AnExpensiveClass> {

    @Override
    public AnExpensiveClass convert(Token token) {
        // Return an instance based on the supplied token (i.e. assume that 
        // the AnExpensiveClass constructor will load data from the database 
        // and populate the instance we're returning).
        return new AnExpensiveClass(token);
    }

    @Override
    public Class<? extends AnExpensiveClass> type(Token token) {
        return AnExpensiveClass.class;
    }

    @Override
    public String id(Token token) {
        return String.valueOf(token.getId());
    }

    @Override
    public String displayName(Token token) {
        return "my lazy loading delegate";
    }
}

----

==== Code that creates a Lookup and registers the InstanceContent:

[source,java]
----

    ic = new InstanceContent();
    al = new AbstractLookup(ic);
        
    Token token = new Token(12345);
    ic.add(token, new LazyLoadingDelegate());

----

Your link:http://bits.netbeans.org/dev/javadoc/org-openide-awt/org/openide/awt/Actions.html#context[context-sensitive action] will behave normally&mdash;it does not need to know about the lazy loading (code not relevant to lazy loading has been removed for the sake of brevity):

[source,java]
----

public final class ExpensiveClassAction implements ActionListener {
    private final AnExpensiveClass expensiveClass;
    public ExpensiveClassAction(AnExpensiveClass a) {
      this.expensiveClass = a;
    }

    public void actionPerformed(ActionEvent ev) {
        // now you have the actual do AnExpensiveClass instance, 
        // in variable expensiveClass
        // so do something with it...
    }
}

----

==== Lifecycle With InstanceContent.Converter

Objects created using an InstanceContent.Converter are only weakly cached by default.  That means that, after AnExpensiveClass is instantiated, it can be garbage collected if no object holds a reference to it in a field.  If the object is going to be queried for repeatedly, you may want your InstanceContent.Converter to cache the last-created value, either for some period of time, or using a SoftReference or hard reference or other caching strategy.

=== Apache Migration Information

The content in this page was kindly donated by Oracle Corp. to the
Apache Software Foundation.

This page was exported from link:http://wiki.netbeans.org/DevFaqLookupLazyLoad[http://wiki.netbeans.org/DevFaqLookupLazyLoad] , 
that was last modified by NetBeans user Jtulach 
on 2010-07-24T20:19:40Z.


*NOTE:* This document was automatically converted to the AsciiDoc format on 2018-02-07, and needs to be reviewed.
