It’s been a while since the last installment of ADF BC Tuning, but it’s time to start it up again. I’ve already posted tips for tuning entity objects, associations, view objects (in three parts), and view links, so now, let’s turn our attention to the last of the major business components: application modules.
The General page of the application module editor, like that for most other editors, has a Tuning section, but for most applications, this section isn’t terribly important. What it does is allow you to choose whether the view object instances and nested application module instances in the data model are loaded immediately (when the application module is loaded), which is the default setting, or are just loaded one by one as they are used.
How long does it take to load a view object instance? Not very long. This is just instantiation, not querying (which is always lazy), plus, if this is the first time an instance of this VO def has been instantiated, loading metadata from the view object definition”s XML file. So if you have a smallish application module with, say, 15 view object instances in the data model, you’re not going to see any difference from lazy loading. It’s only relevant for great big application modules, the kind that have 100+ view object instances, counting those in any non-lazy-loading nested application module instance. In that case, when the application module instance is first created (which is not necessarily every time a user accesses one; we’ll talk about that next week), there can be noticeable overhead, especially for the first AM instance (which requires loading all the VO defs). In that case, you might want to consider lazy loading, especially if there’s a good chance that any given user session won’t actually require all the view object instances. But for most cases, there are much bigger factors that affect performance.
Shared Application Module Instances
I talked about shared application module instances here, but some points bear repeating and emphasizing.
Each business components project allows you to register shared instances of application module definitions. These are, in some ways, a lot like regular top-level application module instances, but they have a few significant differences:
- Their view object instances can be used to supply LOV data for entity attribute validation or to drive dropdown lists and LOV windows for view attributes.
- You can’t access them directly from data bindings (except to populate dropdown lists and LOV windows) without some coding work, which I explain here and here.
- If you share an application module instance at the application level (as opposed to the session level), there is only one instance of that application module, shared by all users.
It’s that last point that interests us here. What does sharing an application module instance across all users mean?
Well, for one thing, it means that if users make any changes to persistent data in the application module instance, they’ll be doing so in the same transaction, which is generally a bad idea. So you should generally query only read-only data from the view object instances inside an application-scoped shared application module instance.
On the other hand, it means there’s only one set of data caches shared by all users. For data that’s read-only within an application (which usually includes LOV data), that can be a huge savings, especially in terms of memory consumed.
It’s also a bit more flexible than you might imagine: For example, you can set bind parameter values, apply view criteria, and even set the sort order on the view accessor level, if you want, meaning that different users at different times can see different subsets of the data if that’s appropriate. The view accessors return a RowSet that has been filtered as desired. This can also result in faster performance (in addition to higher memory efficiency) compared to ordinary application module instances, because while the RowSet isn’t retained after the view accessor uses it, the query collection (actual, filtered set of data) is–so if another request, by any user, is made later for the exact same data (with the same bind parameter values/view criteria), it won’t have to be requeried from the database.
For the majority of applications, I’d say that sharing LOV data this way is substantially more important than implementing lazy-loading. But it’s still not nearly as important as tuning the application module pool–which I’ll post about next week.
Edit: Apparently, you can declaratively access shared application module instances directly from data bindings. Who knew?