bea.com | products | dev2dev | support | askBEA

Download Docs | Site Map | Glossary
Search

Invoking Liquid Data Queries Programmatically

Invoking Queries in EJB Clients

This topic describes how to execute BEA Liquid Data for WebLogicTM queries in EJB clients. It contains the following steps:

- Step 1: Connect to the Liquid Data Server

- Step 2: Specify Query Parameters

- Step 3: Execute the Query

- Step 4: Process the Results of the Query

For more information about EJB clients, see EJB Clients.

Step 1: Connect to the Liquid Data Server

An EJB client may use standard JNDI and EJB calls in order to obtain a reference to the remote interfaces of the query execution session beans.

To do so, a remote client first needs to set up the JNDI initial context by specifying the INITIAL_CONTEXT_FACTORY and PROVIDER_URL environment properties.

- The value of INITIAL_CONTEXT_FACTORY should be set to weblogic.jndi.WLInitialContextFactory.

- The value of PROVIDER_URL should reflect the location (URI) of the application server hosting the Liquid Data Server (for example, t3://localhost:7001).

A local client, i.e. a client that resides on the application server that hosts the Liquid Data Server, may bypass these steps by using the settings in the default context obtained by invoking the empty initial context constructor (i.e. by calling new InitialContext()).

At this stage, the client may also optionally authenticate itself by passing its security context to the corresponding JNDI environment properties SECURITY_PRINCIPAL and SECURITY_CREDENTIALS. Alternatively, the client may use the query execution API as an anonymous (default) user.

Once the JNDI context is set up, the client may use the JNDI names of the remote home interfaces of the stateless query execution session bean in order to perform a lookup and obtain remote references to the EJBHome objects.

The JNDI name for the home interface of the query execution SSB is bea.ldi.server.QueryHome. The home interface may finally be used to obtain references to the EJBObject objects of the session bean.

The JNDI name for the remote interface of the query execution SSB is com.bea.ldi.server.QueryHome. The home interface may finally be used to obtain references to the EJBObject object (com.bea.ldi.server.Query) of the session bean.

The code excerpt below is an example of a remote client that obtains a reference to the EJBObject of the stateless query execution session bean and it illustrates the concepts discussed above:

Listing 2-1 Obtaining a Reference to EJB Object Query

>       import java.util.Hashtable;

>       import javax.naming.Context;

>       import javax.naming.InitialContext;

>       import javax.naming.NamingException;

>       import javax.rmi.PortableRemoteObject;

>       import com.bea.ldi.server.*;

>       ...	// more code

>       private static final String QUERY_HOME_JNDI_NAME = 										"bea.ldi.server.QueryHome";

>         ...	// more code

>       QueryHome queryHome = null;

>       Query query = null;

>       // obtain a remote Query reference

>       try {

>     queryHome = lookupQueryHome();

>     	Object obj = queryHome.create();

>     	query = (com.bea.ldi.server.Query) narrow(obj, com.bea.ldi.server.Query.class);

>       }

>       catch (Exception e) {

>     	// code to handle the exception

>       }

>         ...	// more code

>       /**

>        * Lookup the EJB home in the JNDI tree of the specified Liquid Data Server.

>        */

>       private QueryHome lookupQueryHome()

>         throws NamingException {

>     	Context ctx = getInitialContext();

>     	// Lookup the bean's home using JNDI

>     	Object home = ctx.lookup(QUERY_HOME_JNDI_NAME);

>     return (QueryHome) narrow(home, QueryHome.class);

>       }

>       /**

>        * Obtains the JNDI context.

>        */

>       private Context getInitialContext() throws NamingException {

>     // Set up the environment properties

>      	Hashtable h = new Hashtable();

>          	h.put(Context.INITIAL_CONTEXT_FACTORY,

>           		"weblogic.jndi.WLInitialContextFactory");

>     h.put(Context.PROVIDER_URL, "t3://localhost:7001");

>     	h.put(Context.SECURITY_PRINCIPAL, "username");

>     	h.put(Context.SECURITY_CREDENTIALS, "password");

>     // Get an InitialContext

>     return new InitialContext(h);

>       }

>       /**

>        * RMI/IIOP clients should use this narrow function

>        */

>       private Object narrow(Object ref, Class c) {

>        	return PortableRemoteObject.narrow(ref, c);

>       }

Step 2: Specify Query Parameters

Parameterized queries need to be configured before they are executed. Parameterized queries require the client to specify the values of the query parameters. Query parameters allow for dynamic binding of parts of an XQuery query to values specified at runtime. The presence of a parameter in an XQuery query is manifested through the use of the following notation:

>     $#pname

where pname is a unique name across the query assigned to the parameter. In general, parameters may be used in those places inside a query where a constant could be used. For a list of valid parameter types, see Parameterized Queries.

The following sample query illustrates the use of a parameter inside a query.

Listing 2-2 Parameterized XQuery Query

>     <root>

>     {

>     for $b in document("bib")//book,

>           $pub in $b/publisher

>     where $pub = $#publisher

>     return

>           <result>

>                 {$b/title}
>                 {$b/author}
>           </result>

>     }

>     </root>

The following code excerpt demonstrates the sequence of calls required to set the parameter for such a query using the Liquid Data Server API.

Listing 2-3 Setting Query Parameters

>     import com.bea.ldi.server.common.QueryParameters;

>     ... // more code

>     QueryParameters qp = new QueryParameters();

>     qp.setString("publisher", "Morgan Kaufmann Publishers");

The value of a parameter can be overwritten and reused in a new query execution by setting it to a new value. Using anything other than a String for a parameter name, or setting a parameter value of an invalid type, results in a RuntimeException.

Step 3: Execute the Query

Once the reference to the EJBObject of the query execution session bean has been obtained and the query has been configured by setting any query parameters or attributes, the query is ready to be executed.

When executing a query, its fully qualified name must be used. When the physical location of the query is:

>     repository/stored_queries/dir1/dir2/SQ1.xq

It would be qualified as:

>     dir1.dir1.SQ1

For example, if the query is located at:

>     LDrepository/stored_queries/inventory/widgetsales.xq

the query is qualified as:

>     inventory.widgetsales

The Query remote interface offers a variety of execution calls based on whether the query is parameterized or fixed and whether it is stored or ad hoc.

As an example, assuming that the client has obtained a reference to a Query object, as shown in the following code listing, and the String variable queryString has been loaded with the contents of an ad hoc XQuery query, the following excerpt shows how to obtain the query result.

Listing 2-4 Execution of an Ad Hoc Non-Parameterized Query

>     import com.bea.ldi.server.Query;

>     import com.bea.ldi.server.common.QueryResult;

>     ... // more code

>     Query query = null;

>     ... // obtain reference to Query

>     QueryResult result = null;

>     try {

>           result = query.execute(queryString);

>     }

>     if !(result.isEmpty()){

>     ... // process result

>     }

>     else {

>     ... // query returned no data

>     }

>     catch(RemoteException e) {

>           // code to handle the exception

>     }

>     finally {

>           try {

>           query.remove();

>     }

>     catch(Exception e) {

>         // code to handle the exception

>           }

>     }

If a stored query is to be executed, then call executeStored(queryName), where the String variable queryName is assumed to contain the name of the stored query to be executed.

If the query is parameterized, once the query parameters have been set, they should be passed in the execution call, that is, the execute(queryString) call should be replaced with the calls execute(queryString, qp) and executeStored(queryName, qp) in the case of ad hoc and stored queries respectively. The QueryParameters variable qp in the previous calls is assumed to be loaded with the query parameters.

Note that all execution calls are remote and therefore they may throw a RemoteException, which should be handled by the client. Note also, that once the query result has been retrieved, the client may release resources by removing the EJBObject. If the query is parameterized, the client may use the Query reference to execute the same query multiple times, possibly setting different values for the query parameters each time, before removing the EJBObject. In any case, other server-side resources related to query execution (for example, database cursors) are automatically released once a query has been executed.

Step 4: Process the Results of the Query

Further processing of the query result at the client side may take various forms ranging from merely extracting, or printing out the XML string to using the DOM representation of the result in order to drill into specific subsets of it.

The result is fully materialized on the server in the form of an unformatted XML string, which is transmitted to the client. The client may then extract the XML content of the query result as a String using toXML() method. Alternatively, the client may use the getDocument() call in order to obtain the DOM representation of the result, provided that a JAXP-compliant parser is available in the client environment. In either case, the client is free to process the result using any XML processor (for example, using an XSLT processor to convert the result to a presentable format like HTML).