Sunday, June 24, 2007

Hibernate fetching strategies

A fetching strategy is the strategy Hibernate will use for retrieving associated objects if the application needs to navigate the association. Fetch strategies may be declared in the O/R mapping metadata, or over-ridden by a particular HQL or Criteria query.

Hibernate3 defines the following fetching strategies:

  • Join fetching - Hibernate retrieves the associated instance or collection in the same SELECT, using an OUTER JOIN.

    <set name="permissions" fetch="join">
    <key column="userId"/>
    <one-to-many class="Permission"/>
    </set


    <many-to-one name="mother" class="Cat" fetch="join"/>


    Can be specified at query level:


    User user = (User) session.createCriteria(User.class)
    .setFetchMode("permissions", FetchMode.JOIN)
    .add( Restrictions.idEq(userId) )
    .uniqueResult();
  • Select fetching - a second SELECT is used to retrieve the associated entity or collection. Unless you explicitly disable lazy fetching by specifying lazy="false", this second select will only be executed when you actually access the association. Use fetch="select" or FetchMode?.Select to accomplish this.
  • Subselect fetching - a second SELECT is used to retrieve the associated collections for all entities retrieved in a previous query or fetch. Unless you explicitly disable lazy fetching by specifying lazy="false", this second select will only be executed when you actually access the association. Use fetch="subselect" or FetchMode?.SubSelect? to accomplish this.

* Batch fetching - an optimization strategy for select fetching - Hibernate retrieves a batch of entity instances or collections in a single SELECT, by specifying a list of primary keys or foreign keys. You may also enable batch fetching of collections. For example, if each Person has a lazy collection of Cats, and 10 persons are currently loaded in the Sesssion, iterating through all persons will generate 10 SELECTs, one for every call to getCats(). If you enable batch fetching for the cats collection in the mapping of Person, Hibernate can pre-fetch collections. With a batch-size of 8, Hibernate will load 3, 3, 3, 1 collections in four SELECTs. Again, the value of the attribute depends on the expected number of uninitialized collections in a particular Session. Batch fetching of collections is particularly useful if you have a nested tree of items, ie. the typical bill-of-materials pattern. (Although a nested set or a materialized path might be a better option for read-mostly trees.)

<class name="Person">
<set name="cats" batch-size="3">
...
</set>
</class>


Hibernate also distinguishes between:

  • Immediate fetching - an association, collection or attribute is fetched immediately, when the owner is loaded.
  • Lazy collection fetching - a collection is fetched when the application invokes an operation upon that collection. (This is the default for collections.)
  • "Extra-lazy" collection fetching - individual elements of the collection are accessed from the database as needed. Hibernate tries not to fetch the whole collection into memory unless absolutely needed (suitable for very large collections)
  • Proxy fetching - a single-valued association is fetched when a method other than the identifier getter is invoked upon the associated object.
  • "No-proxy" fetching - a single-valued association is fetched when the instance variable is accessed. Compared to proxy fetching, this approach is less lazy (the association is fetched even when only the identifier is accessed) but more transparent, since no proxy is visible to the application. This approach requires buildtime bytecode instrumentation and is rarely necessary.
  • Lazy attribute fetching - an attribute or single valued association is fetched when the instance variable is accessed. This approach requires buildtime bytecode instrumentation and is rarely necessary.

By default, Hibernate3 uses lazy select fetching for collections and lazy proxy fetching for single-valued associations. These defaults make sense for almost all associations in almost all applications.


To enable lazy property loading, set the lazy attribute on your particular property mappings:

<class name="Document">
<id name="id">
<generator class="native"/>
</id>
<property name="name" not-null="true" length="50"/>
<property name="summary" not-null="true" length="200" lazy="true"/>
<property name="text" not-null="true" length="2000" lazy="true"/>
</class>

Saturday, June 09, 2007

XWORK external reference resolver

XWORK external reference resolver


Sometimes xwork action classes needs to be wired with external references, for example spring maintained resources. In such cases the dependencies are defined using a <external-ref> tag. For example: see below a sample xwork configuration wherein an action class needs to be wired with a spring maintained datasource:



<package name="auditIntegration" extends="auditResultRun">
<action name="executeAllAudits" class="com.xxx.AllSchemasAuditAction">
<external-ref name="dataSource" required="true">/db/dw/DataSource</external-ref>
<param name="nestedActionName">executeAudit</param>
</action>
</package>


In such cases external resolvers need to be specified which perform the property setting. XWORK provides a specification using com.opensymphony.xwork.config.ExternalReferenceResolver and provides a default implementation com.opensymphony.xwork.spring.SpringExternalReferenceResolver for spring reference resolver. Custom implementation can be provided to resolve other external references like JNDI dependencies into xwork etc. In any case these external resolvers must be explicitly declared to be used by XWORK. See below for a sample declaration (extends the webwork default config):



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN" "http://www.opensymphony.com/xwork/xwork-1.0.dtd">
<xwork>
<include file="webwork-default.xml"/>
<package name="xwork-common" extends="webwork-default"
externalReferenceResolver="com.xxx.SpringExternalReferenceResolver">
</package>
</xwork>



Sample implementation for the external resolver (code adapted from XWORK com.opensymphony.xwork.spring.SpringExternalReferenceResolver implementation):



public class SpringExternalReferenceResolver implements com.opensymphony.xwork.config.ExternalReferenceResolver
{
private static final Logger log = Logger.getLogger(SpringExternalReferenceResolver.class);

/**
* resolve the references for this invocation
* @param invocation the invocation to resolve
* @throws ReferenceResolverException if we had issues.
*/
public void resolveReferences(ActionInvocation invocation) throws ReferenceResolverException
{
ApplicationContext ctx = {{get app context handle here}};
if (ctx == null)
throw new IllegalStateException("application context has not been set for this "
+ "external reference resolver!");

List externalRefs = invocation.getProxy().getConfig().getExternalRefs();
for (Iterator iter = externalRefs.iterator(); iter.hasNext(); )
{
ExternalReference reference = (ExternalReference) iter.next();
if (log.isDebugEnabled())
log.debug("resolving " + reference.getName() + " to " + reference.getExternalRef());
if (reference.getExternalRef() == null)
{
throw new ReferenceResolverException(
"reference " + reference.getName() + " has no external ref");
}

Object bean = null;
try
{
// no such bean exception
bean = ctx.getBean(reference.getExternalRef());
if (log.isDebugEnabled())
log.debug("resolved " + reference.getExternalRef() + " to " +
(bean != null ? bean.getClass().toString() : "null"));

// other exceptions
Map context = Ognl.createDefaultContext(invocation.getAction());
if (log.isDebugEnabled())
log.debug("setting bean into property " + reference.getName() + " of " +
invocation.getAction().getClass());

// unbelievably, this actually throws a RuntimeException! Unbelievable
OgnlUtil.setProperty(reference.getName(), bean, invocation.getAction(),
context, true);
if (log.isDebugEnabled())
log.debug("resolved " + reference.getName() + " to " +
reference.getExternalRef() + ": " + bean);
}
catch (NoSuchBeanDefinitionException e)
{
if (reference.isRequired())
{
//if a dependency is required but wasn't found throw an exception
throw new ReferenceResolverException(
"Failed to find external reference: " + reference.getExternalRef(), e);
}
else
{
log.warn("Bean '" + reference.getExternalRef() +
"' could not be found in spring");
// just keep going
continue;
}
}
catch (Exception e)
{
throw new ReferenceResolverException(
"Failed to set external reference: " + reference.getExternalRef()
+ " for bean attribute: " + reference.getName() + ": " + e.getMessage() +
" bean hashcode: " + (bean != null ? bean.getClass().hashCode() : -1), e);
}
}
if (log.isDebugEnabled())
log.debug("external reference resolution for " + invocation.getAction() + " complete.");
}


}

WS-BPEL

- What is WS-BPEL?

An XML-based grammar for describing the logic to orchestrate the interaction between Web services in a business process. It defines a set of basic control structures like conditions or loops as well as elements to invoke web services and receive messages from services. It relies on WSDL to express web services interfaces. Message structures can be manipulated, assigning parts or the whole of them to variables that can in turn be used to send other messages.

- Why is it needed?

• Web services --> move towards service-oriented computing
• Applications are viewed as “services”
• Loosely coupled, dynamic interactions
• Heterogeneous platforms
• No single party has complete control
• How do you compose services in this domain?
• WSDL defined Web services have a stateless interaction model
• Messages are exchanged using
• Synchronous invocation
• Uncorrelated asynchronous invocations
• Most “real-world” business processes require a more robust interaction model
• Support for Messages exchanged in a two-way, peer-to-peer conversation lasting minutes, hours, days, etc.
• BPEL provides the ability to express stateful, long-running interactions


- Relationship with WSDL?

BPEL is layered on top of and extends the WSDL service model
• WSDL defines the specific operations allowed
• BPEL defines how WSDL operations are orchestrated to satisfy a business process
• BPEL also specifies extensions to WSDL in support of long-running asynchronous business processes
• Expressed entirely in XML
• Uses and extends WSDL 1.1
• Uses XML Schema 1.0 for the data model

- What is Apache ODE?
Apache ODE (Orchestration Director Engine) executes business processes written following the WS-BPEL standard. It talks to web services, sending and receiving messages, handling data manipulation and error recovery as described by your process definition. It supports both long and short living process executions to orchestrate all the services that are part of your application.


- References
Real use cases scenarios