Search Queries  Locate

In this section we will explain

Modifying Simple Queries  Locate

The query can be constructed by the Java code that belongs to the Web UI component, but there is a much simpler way: you can use the parseUddiQuery JSP tag. Here's an example that constructs a query that works with portType tModels.

Example 28. Query that Finds WSI-Compliant Interfaces

<bsc:parseUddiQuery var="findQuery" scope="request">
    <find_binding xmlns="urn:uddi-org:api_v3">
        <findQualifiers>
            <findQualifier>
                uddi:uddi.org:findqualifier:approximatematch
            </findQualifier>
        </findQualifiers>
        <categoryBag>
            <keyedReference tModelKey="uddi:65719168-72c6-3f29-8c20-62defb0961c0" 
             keyValue="%"/>
            <keyedReference tModelKey="uddi:uddi.org:wsdl:types" 
             keyValue="portType"/>
        </categoryBag>
    </find_binding>
</bsc:parseUddiQuery>

The tag can be put anywhere in the JSP. It does not render anything to the output but stores the UDDI query structure into the output variable.

When you need to add additional filters to your query, you may use the selectCategory component to add KeyedReferences to the query's categoryBag. In this way you can refine the search criteria of a query that was passed to the page and make your Web UI components more reusable.

In Example 29, we add a stability filter to the query constructed in the previous section:

Example 29. Adding a Stability Filter to an Existing Query

<!-- We are going to modify an existing query -->
<syswf:component name="selectCategory" prefix="stableInterfaces">
    <!-- Pass in the variable name. It will be modified in-place -->
    <syswf:param name="var" value="findQuery"/>
    <!-- We are searching for entities that have the category present, regardless of
         the keyValue of the KeyedReference
    -->
    <syswf:param name="category" value="uddi:65719168-72c6-3f29-8c20-62defb0961c0"/>
</syswf:component>

Creating Complex Search Queries  Locate

The searching pattern of the Business Service Console accepts various parameters entered by the user. In order to create a search query component, follow these steps:

Before we discuss the steps above in much detail, let's look at how search queries work:

  1. The user starts searching. For example, the user clicks on the Search Providers link under the Search main menu tab.

  2. The process method is invoked in the Component's java code and produces the FindProvidersView instance in a session variable.

  3. Components present on the page take values from the FindProvidersView instance, using getter methods of the Java Bean.

  4. The user enters some characters into the input field.

  5. Eventually, the user clicks the Find button.

  6. The Search task is re-entered, since the <syswf:control> tag does not specify any target task for the button's action. The <syswf:control> does, however, provide the action string to the task.

  7. The process method is invoked again, this time with the action set to the appropriate value. At the same time, the framework sets form's values to the bean. The java code takes the FindProvidersView properties and create the UDDI query from it. It also sets the focusTab session variable, so that the Results <div> content becomes visible.

  8. The JSP page displays again, but this time, the Results portion is visible.

Creating A User Input Bean  Locate

You may want several input fields to be present on the page. Systinet Web Framework and the Business Service Console framework provide components that work with JavaBeans and place user input into JavaBean properties. We recommend creating one or a small number of JavaBeans to hold the input from the entire page rather than having the input scattered into many session or request variables. These JavaBeans must implement the Serializable interface, otherwise a NotSerializableException will be thrown when switching to the next HTML page.

Example 30. Simple Bean For Holding the User Input

package com.systinet.uddi.bui.standard.view;

import java.io.Serializable;

/**
 * This class is a simple Java Bean, that keeps all the search criteria 
 * at one place accessible
 * from JSPs through getters and setters.
 */
public class FindProvidersView implements Serializable {
    /**
     * Name of the Provider
     */
    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Components that render the form fields will use the bean's getter and setter to manipulate the values. The Java part of the search Component will then get the value and create the UDDI find structure.

Creating A Component in Java  Locate

A Java component transforms the user input into a UDDI find structure that can be processed by other Business Service Console UI components. You can use the code in Example 31 as a boilerplate for your search components:

Example 31. Java Code for Search Components

import com.systinet.uddi.bui.framework.BUIFrameworkErrorCodes;
import com.systinet.uddi.bui.framework.BUIFrameworkException;
import com.systinet.uddi.bui.standard.util.BUIConstants;
import com.systinet.uddi.bui.standard.view.FindProvidersView;
import com.systinet.webfw.ComponentImpl;
import com.systinet.webfw.WebFrameworkException;
import com.systinet.webfw.servlet.WebRequest;
import org.systinet.uddi.InvalidParameterException;
import org.systinet.uddi.client.v3.struct.FindQualifierConstants;
import org.systinet.uddi.client.v3.struct.Find_business;
import org.systinet.uddi.client.v3.struct.Name;

import java.util.Map;

public class SimpleSearch extends ComponentImpl {
    /**
     * Name of the "findProviders" variable
     */
    static final String VAR_FIND_PROVIDERS = "findProviders";

    /**
     * Name of the action that triggers the conversion.
     */
    static final String ACTION_FIND_PROVIDERS = "findProviders";

    /**
     * The variable that controls which of the tabs is visible.
     */
    public static final String VAR_FOCUS_TAB = "focusTab";

    /**
     * This method will be called:
     * - when the Component is displayed
     * - when the Find button is pressed. In this case, the action 
     * string will be passed to this method.
     */
    public void process(String action, Map params) throws WebFrameworkException {
        // Get the current session where the "view structure" will be stored.
        Map session = getCurrentSession();
        WebRequest request = (WebRequest) getRequest();

        try {
            // Get the view structure
            FindProvidersView findView = (FindProvidersView) 
                  session.get(VAR_FIND_PROVIDERS);
            if (findView == null) {
                // If there is no structure present, we are entering the search page. 
                //We will select the "Search" tab by setting the appropriate 
                // Request attribute:
                findView = new FindProvidersView();
                session.put(VAR_FIND_PROVIDERS, findView);
                request.setAttribute(VAR_FOCUS_TAB, "fsearch");
            }

            // This action is sent by the "Find" button, we will make a query from 
            // the entereed data.
            if (ACTION_FIND_PROVIDERS.equals(action)) {
                // Create the query structure
                Find_business find = new Find_business();
                // The user usually does not enter complete input, so we will 
                // search approximately
                find.addFindQualifier(FindQualifierConstants.FQ_APPROXIMATE_MATCH_KEY);

                // If the user has entered the name of the entity, place 
                // it into the query.
                if (findView.getName() != null) {
                    find.addName(new Name(findView.getName()));
                }
                // Focus the "results" tab
                session.put(BUIConstants.VAR_FOCUS_TAB, BUIConstants.TAB_RESULTS);
                // Put the query into the session variable, so other components can find it
                session.put(BUIConstants.VAR_FIND_QUERY, find);
                // In the case of provider search result view, there's is a result cache.
                // Since we are running a new query, we need to reset the cache.
                session.remove(BUIConstants.VAR_PROVIDER_RESULTS);
            }
        } catch (InvalidParameterException e) {
            // Simple error handling - the InvalidParameterException should 
            // never be thrown.
            throw new BUIFrameworkException(BUIFrameworkErrorCodes.UDDI_ERROR, e);
        }
    }
}

There are two important parts in the Java code:

  • First, the FindProvidersView instance must be present in order for the JSP to work correctly. The Java component must construct it and place it in a session variable. If the bean instance is not present, the <syswf:input> component will fail to operate properly.

  • Second, is the reaction to the action string. The action is passed to the task when the user presses the Find button. In Inserting Components into the JSP for the Search Page, the button loops back to the page's task itself, but passes the action string.

We need to process the FindProvidersView bean properties and create the UDDI query from them. In this example, there is only the name.

Inserting Components into the JSP for the Search Page  Locate

Search pages in the Business Service Console use a tabbed design. The first tab holds the search criteria while the second tab displays the search results. The same task serves to both the search criteria form and the search results form. Insert the following fragment to your JSP page as shown in Example 32:

<syswf:param name="btn_2_caption" value="Find"/>
    <syswf:param name="btn_2_action">
    <!-- The action will be taken on this Task there's no targetTask) -->
    <syswf:control action="findProviders" mode="script">
    <!-- Let the Java code know which tab we want to select -->
    <syswf:param name="focusTab" value="fresults"/>
    </syswf:control>
</syswf:param>
<syswf:param name="btn_2_width" value="150"/>
<syswf:param name="btn_2_enabled" value="true"/>
Use a Component for Displaying Results  Locate

Insert the following fragment to your JSP page as shown in Example 32

<syswf:component prefix="resultView" name="providerSearchResults">
      <syswf:param name="defaultView" value="providersCommonResults" />
      <syswf:param name="prefix" value="providers" />
      <syswf:param name="query" value="${findQuery}"/>
</syswf:component>
            

Example 32 shows a skeleton for the search page. You may refer to the search/providers/simple.jsp for real-world code that implements the Providers search.

Example 32. Search Page Skeleton

<!-- The page header, navigation tree etc are omitted -->

<%--  The search pane, consisting of Search and Results tab  --%>
<syswf:wrap headerTemplate="design/searchTabsHeader.jsp" 
    footerTemplate="design/searchTabsFooter.jsp">
    <!-- The ID of the search.  -->
    <syswf:param name="searchId" value="findProvider"/>

    <!-- The ID of the tab, that should receive the focus. The variable will be set
         by this Component's java part
    -->
    <syswf:param name="focusTab" value="${focusTab}"/>

    <!-- Contents of the Search tab -->
    <div id="fsearch" name="fsearch" style="display:block;">
        <syswf:wrap headerTemplate="design/normalFrameHeader.jsp" 
         footerTemplate="design/searchTabbedFrameFooter.jsp">
            <!-- Use the contentId to distinguish content areas of the two tabs for
                 the javascripts -->
            <syswf:param name="contentId" value="1"/>

            <!-- First button, counting from the left -->
            <syswf:param name="btn_1_caption" value="Cancel"/>
            <!-- This action will pop up one task, so when used, 
            the Console will return to the previous state -->
            <syswf:param name="btn_1_action"><syswf:control 
            targetDepth="${sessionStack.currentDepth-1}" mode="script"/>
            </syswf:param>
            <syswf:param name="btn_1_width" value="150"/>
            <!-- Cancel is always enabled -->
            <syswf:param name="btn_1_enabled" value="true"/>

            <!-- The second buttonm, that actually performs the search -->
            <syswf:param name="btn_2_caption" value="Find"/>
            <syswf:param name="btn_2_action">
                <!-- The action will be taken on this Task 
                (there's no targetTask) -->
                <syswf:control action="findProviders" mode="script">
                    <!-- Let the Java code know which tab we want 
                    to select -->
                    <syswf:param name="focusTab" value="fresults"/>
                </syswf:control>
            </syswf:param>
            <syswf:param name="btn_2_width" value="150"/>
            <syswf:param name="btn_2_enabled" value="true"/>

            <!-- This is the content of the page. 
             We simplified it a lot from the real pages -->
            <div class="DialogHelp">Fill in one or more of following fields 
            (use % as wildcard). You can also leave all fields blank
            to search for all Providers published in the Systinet Registry.</div>

            Name: &nbsp;
            <!-- This is a standard Systinet Web Framework input component.
                 It will store the entered text into the "name" property of the
                 bean found in "findProviders" variable
            -->
            <syswf:input name="name" value="${findProviders}" property="name" >
                <syswf:attribute name="class" value="INPUTborder"/>
                <syswf:attribute name="size" value="50"/>
            </syswf:input>
            </syswf:wrap>
        </div> <%-- End of the search tab contents --%>

        <%-- The "Results" tab contents --%>
        <div id="fresults" style="display:none">
            <!-- We want the results to be printable, so we include 
            a different header for this tab -->
            <syswf:wrap headerTemplate="design/printableFrameHeader.jsp"
            footerTemplate="design/searchNormalFrameFooter.jsp">
                <syswf:param name="frameWidth" value="100%"/>
                <!-- We use a different contentId, so the content area can scroll 
                independently -->
                <syswf:param name="contentId" value="2"/>

                <!-- If there is no query to perform, there can be no results 
                to display -->
                <c:if test="${not empty findQuery}">

                    <!-- Run the query and display results of it. The 
                    query structure is passed in the
                         "query" parameter
                    -->
                    <syswf:component prefix="resultView" name="providerSearchResults">
                        <syswf:param name="defaultView" value="providersCommonResults" />
                        <syswf:param name="prefix" value="providers" />
                        <syswf:param name="query" value="${findQuery}"/>
                    </syswf:component>
                </c:if>
            </syswf:wrap>
        </div>
</syswf:wrap>

Displaying Search Results  Locate

Once the UDDI query is created, a component can be used to execute the query and display the results. The following components are already present in Business Service Console:

Each of those components accepts a UDDI query structure as a parameter and will render a page with results that allows the user to choose a view.