11 Integrating Service-Enabled Application Modules

This chapter describes how to publish ADF application modules to make them available as external services in a composite Fusion web application, and how to incorporate the published application module as an external service in the composite Fusion web application.

This chapter includes the following sections:

11.1 Introduction to Service-Enabled Application Modules

Service-enabled application modules are ADF application modules that you advertise through a service interface to service consumers. There are three scenarios for service consumers to consume a published service-enabled application module: web service access, Service Component Architecture (SCA) composite access, and access by another ADF application module.

Note:

For background about web services and Oracle WebLogic Server support for web services, see Oracle Fusion Middleware Introducing Web Services.

Service Component Architecture (SCA) provides an open, technology-neutral model for implementing remotable services that are defined in terms of business functionality and that make middleware functions more accessible to application developers. ADF Business Components supports an SCA-compliant solution through application modules you can publish with a service interface. Any development team can publish a service-enabled application module to contribute to the composite Fusion web application. The Fusion web application assembled from remote services also does not require the participating services to run on a single application server.

Although composite applications often run on separate application servers, the appearance that SCA provides is one of a unified application. Consuming client projects use the ADF service factory lookup mechanism to access the data and any business methods encapsulated by the service-enabled application module. At runtime, the calling client and the ADF service may or may not participate in the same transaction, depending on the protocol used to invoke the service (either SOAP or RMI). Only the RMI protocol and a Java Transaction API (JTA) managed transaction support the option to call the service in the same transaction as the calling client. By default, to support the RMI protocol, the ADF service is configured to participate in the same transaction.

When you service-enable your application module, JDeveloper generates the necessary artifacts comprising: 1) The Java interface defining the service, 2) an EJB 3.0 session bean that implements this Java interface, 3) a WSDL file that describes the service's operations, and (4) an XML Schema Document (XSD) that defines the service's data structures. The service interface is described for Fusion web application clients in a language-neutral way by the combination of WSDL and XSD.

Note:

SCA defines two kinds of service:
  • Remoteable services, typically coarse-grained and designed to be published remotely in a loosely coupled SOA architecture

  • Local services, typically fine-grained and designed to be used locally by other implementations that are deployed concurrently in a tightly coupled architecture

ADF Business Components services fall into the first category, and should only be used as remoteable services. For local service support, use the ApplicationModule interface and ViewObject interface support described in Section 9.10, "Working Programmatically with an Application Module's Client Interface."

Services, including data access and method calls, defined by the remote application modules are interoperable with any other application module. This means the same application module can support interactive web user interfaces using ADF data controls and web service clients.

The common mechanism for invoking components such as a BPEL process is used by the ADF connection architecture to invoke a replaced service implementation (see Section 13.2, "Calling a Web Service from an Application Module") and a generic web service provider handles any application invocation that takes DataObject arguments and returns DataObject.

For information about the SCA and SDO standards, see the Open SOA web site at http://www.osoa.org.

11.2 Publishing Service-Enabled Application Modules

The application module is ADF Business Components framework component that encapsulates business logic as a set of related business functions. Application modules are mapped to services. You use the overview editor for your application module to enable a web service interface and publish rows of view object data as Service Data Object (SDO) components. The SDO framework upon which these components are based abstracts the data of the view object and standardizes the way that data structures are passed between Java and XML. This data abstraction simplifies working with heterogeneous data sources in a service-oriented architecture (SOA) and lets you selectively service-enable view objects using the same view object to support interactive web user interfaces and web service clients.

JDeveloper allows you to expose application modules as web services which use SDOs to standardize the way that data structures are passed between Java and XML. JDeveloper also generates the WSDL service description that is used by the web service client in the consuming application.

The service-enabled application module exposes the view objects, custom methods, built-in data manipulation operations, and specialized find methods based on named view criteria to be used by the client. Once you have enabled the application module service interface, you will need to create an ADF Business Components Service Interface deployment profile and deploy it to the target application server.

You can also expose the view instance data manipulation operations for use with a Business Process Execution Language (BPEL) process service component. BPEL is a language for composing multiple services into an end-to-end business process. For details about how to delegate data operations to the SDO data provider through the use of the BPEL entity variable, see the Oracle Fusion Middleware Developer's Guide for Oracle SOA Suite.

Note:

It is important to note that you don't implement methods with SDO parameters directly. The SDO framework is used to wrap the view row types during runtime only.

11.2.1 How to Enable the Application Module Service Interface

You edit the application module in JDeveloper to create a web service interface that exposes the top-level view objects and defines the available service operations it supports. The top-level view objects that you select are service-enabled automatically and will be accessible by the service client.

The primary purpose of the standard service operations is to expose data manipulation operations on the view objects. Any business logic that you have defined on the underlying framework objects (for example, business rule validation) will be applied when you invoke a standard service operation. Table 11-1 shows the list of standard operations that service view instances support.

Table 11-1 Standard View Instance Data Manipulation Operations

Operation Method Name Operation Description

Create

create<VOName>

Creates a single ADF Business Components view row.

Update

update<VOName>

Updates a single ADF Business Components view row.

Delete

delete<VOName>

Deletes a single ADF Business Components view row.

Merge

merge<VOName>

Updates a ADF Business Components view row if one exists; otherwise, creates a new one.

GetByKey

get<VOName>

Gets a single ADF Business Components view row by primary key.

Find (by view object query statement)

find<VOName>

Finds and returns a list of ADF Business Components view rows based on the selected view object's query statement.

Note that the query must not specify a bind variable defined as required for the query to execute. The service interface does not expose required bind variables at runtime. For details about creating a find method for this scenario, see Section 11.2.8, "How to Expose a Declarative Find Operation Filtered By a Required Bind Variable."

Find (by view criteria)

find<VOName><VCName>

Finds and returns a list of single ADF Business Components view rows by SDO-based view criteria. This is the preferred way to filter the ADF Business Components view rows that rely on a required bind variable.

Process

process<VOName>

Performs a Create, Update, Delete, or Merge operation on a list of ADF Business Components view rows. The specified operation is applied to all objects in the given list.

ProcessChangeSummary

processCS<VOName>

Performs a Create, Update, or Delete operation on a list of ADF Business Components view rows. Different operations may be applied to different objects, depending on what is specified in the ChangeSummary object.


Note:

When you enable the service interface on a parent view object, JDeveloper automatically enables the service interface for view instances that extend the parent in a polymorphic collection. For details about polymorphic view objects, see Section 39.6.5, "Working with Polymorphic View Rows."

For information on how to create SDO classes to selectively service-enable child view objects, see Section 11.2.4, "How to Service-Enable Individual View Objects."

Before you begin:

Create the desired application module as described in Section 9.2.1, "How to Create an Application Module."

To create the web service:

  1. In the Application Navigator, double-click the application module.

  2. In the overview editor, click the Service Interface navigation tab and click the Enable support for Service Interface button.

    Use the Create Service Interface wizard to configure the desired options.

  3. In Create Service Interface wizard, on the Service Interface page, enter the name and target namespace for the web service.

    The target namespace is a URI for the service that you can assign to group similar services together by entering the same URI.

  4. To generate a method that will return the static control hints (UI hints) defined on the service view instances that you enable, select Generate Control Hints Operation.

    When you enable this option, the wizard adds the getDfltCtrlHints() method to the service interface. The service interface client can invoke this method to resolve UI hints on the server without requiring a database roundtrip. The method takes the view object name and a locale and returns the base UI hints for that locale.

  5. To expose the methods of the application module as asynchronous service methods and enable both synchronous and asynchronous operations on the web service, select Generate Asynchronous Web Service Methods.

    By default, the web service supports synchronous service methods. This forces the invoking client application to wait for the response to return before it can continue with its work. In cases where the response returns immediately, this method of invoking the web service is common. However, because request processing can be delayed, it is often useful for the client application to continue its work and to handle the response later on.

  6. On the Service Custom Methods page, add the custom methods you want to expose in the service interface and define the data types of each method's parameters and return value.

    The parameters and non-void return value of the custom service methods you enable must be one of the supported data types, such as a primitive Java type, oracle.jbo.server.ViewRowImpl, java.util.List<ViewRowImpl>, oracle.jbo.AttributeList, or java.util.List<AttributeList>.

    Note that although both ViewRowImpl and AttributeList data types expose the identical row structure to the web service client, at runtime there will be a fundamental difference. For a description of the supported data types, see Section 11.2.3, "What You May Need to Know About Method Signatures on the Service Interface."

    After selecting a qualifying custom method to appear in the service interface, for each parameter and return value using the ViewRowImpl or AttributeList data type, you must in turn select the name of the view object instance corresponding to the row structure:

    1. In the Selected list, expand return or parameters and select the item.

    2. Enter the Java element data type in Element Java Type.

    3. In the case where the Java element type is ViewRowImpl or AttributeList, enter the view object instance name to identify the row structure in Element View Object.

      For example, if you define a custom method to return a single row of the CustomerInfo view object instance, you would need a custom method signature like this:

      public ViewRowImpl findCustomerInfo(int id)
      

      Then, after selecting the findCustomerInfo() custom method to appear in the service interface, you would select its return value in the tree and configure its View Object property to be CustomerInfo, the view instance name whose row structure should be used at runtime.

  7. On the Service View Instances page, select the top-level view instances in the application module that you want to expose in the service interface.

    View object subtypes of the top-level view instance will automatically be service-enabled.

    Also, on this page, you can set the available data manipulation operations supported on the exposed methods, as shown in Figure 11-1.

    Figure 11-1 View Instances and CRUD Operation Selection

    View Instances and CRUD Operation Selection
  8. In the Basic Operations tab, select the data manipulation operations for the currently selected view instance.

    The primary purpose of the standard service operations is to expose data manipulation operations on the view objects. Any business logic that you have defined on the underlying framework objects (for example, business rule validation) will be applied when you invoke the service operations. For a description of the operations that service view instances support, see Table 11-1.

    In the case of the find method operation that you can select, the find method must not reference a required bind variable in the view object's query statement. A required bind variable is one that makes the query execution dependent on the availability of a valid value for the bind variable. The service interface does not expose required bind variables at runtime. For details about defining a find operation for this scenario, see Section 11.2.8, "How to Expose a Declarative Find Operation Filtered By a Required Bind Variable."

  9. To expose declarative find operations, select the View Criteria Find Operations tab and click the Add View Criteria icon.

    You can define custom find operations when you want the service to support executing a predefined query. For information about defining a named view criteria, see Section 5.11, "Working with Named View Criteria."

    Caution:

    The service interface find operations are based on specific view criteria that your project defines. This means that that the bind variables of the view criteria must match the parameters of the corresponding find operation method. If you change the number or order of the bind variables after the find operation is defined and service interface generated, the corresponding method will not execute at runtime. Therefore, after changing the underlying view criteria, you must regenerate the service interface.
    1. In the Configure View Criteria Find Operation dialog, choose the named view criteria for the find operation.

      The dialog displays the list of view criteria exposed by the referenced view object. For example, OrderInfoVO defines OrderInfoVOCriteria with a bind variable OrdId that specifies the order ID, as shown in Figure 11-2.

      Figure 11-2 Specialized Find Methods Based on Named View Criteria

      Configure View Criteria Find Operation dialog
    2. If the view criteria uses a bind variable, you can double-click the XML name to customize the name as it will appear in the XML definition for the service.

  10. Click Next to review the custom methods that your service view instances will expose.

  11. Click Finish.

11.2.2 What Happens When You Create an Application Module Service Interface

JDeveloper generates the service interface class and enables any view instance options you have chosen, as shown in Figure 11-3.

Figure 11-3 Service Interface Page of the Overview Editor for an Application Module

Service interface page shows the options you have chosen

The following types of files are generated and are listed in the Application Navigator in the Projects panel, under the application module's serviceinterface node, as shown in Figure 11-4.

  • Remote common interface, for example, StoreFrontService.java

  • Remote service schema file, for example, StoreFrontService.xsd

  • Remote service definition file, for example, StoreFrontService.wsdl

  • Remote server class, for example, StoreFrontServiceImpl.java

Figure 11-4 Service Interface Files Appear Below Application Module

Application Navigator displays serviceinterface contents

In addition, the connections.xml file is created when you first create an ADF Business Components service. This file appears in the Application Navigator in the Application Resources panel, under the Descriptors and ADF META-INF folders.

11.2.2.1 Remote Common Interface

The remote common interface uses metadata annotations specified by the web service specification (JSR-181) to indicate how the interface should be exposed as a web service. This example shows part of StoreFrontService.java, which is the remote common class for the StoreServiceAM application module in the StoreFront module of the Fusion Order Demo.

Example 11-1 Remote Common Interface in Fusion Order Demo

package oracle.fodemo.storefront.store.service.common.serviceinteface;
...
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.soap.SOAPBinding;
...
import oracle.fodemo.storefront.store.queries.common.CustomerInfoVOSDO;
import oracle.fodemo.storefront.store.queries.common.OrderInfoVOSDO;
...
import oracle.webservices.annotations.PortableWebService;
import oracle.webservices.annotations.SDODatabinding;
...
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.WRAPPED, style=SOAPBinding.Style.DOCUMENT)
@PortableWebService(targetNamespace="http://www.globalcompany.com/StoreFrontService",
    name="StoreFrontService", 
    wsdlLocation=
            "oracle/fodemo/storefront/store/service/common/serviceinteface/StoreFrontService.wsdl")
@SDODatabinding(schemaLocation=
            "oracle/fodemo/storefront/store/service/common/serviceinteface/StoreFrontService.xsd")
public interface StoreFrontService 
{
    public static final String NAME = ("http://www.globalcompany.com/StoreFrontService")

    /**
     * @param orderId
     * @return
     * @throws ServiceException
     */
    @WebMethod(action="www.globalcompany.example.com/getOrderInfoVOSDO",
        operationName="getOrderInfoVOSDO")
    @RequestWrapper(targetNamespace="www.globalcompany.example.com/types/",
        localName="getOrderInfoVOSDO")
    @ResponseWrapper(targetNamespace="www.globalcompany.example.com/types/",
        localName="getOrderInfoVOSDOResponse")
    @WebResult(name="result")
    OrderInfoVOSDO getOrderInfoVOSDO(@WebParam(mode = WebParam.Mode.IN, name="orderId")
        BigInteger orderId) throws ServiceException;
    ...
}

11.2.2.2 Remote Service Schema File

The remote service schema file is an XML schema file which represents the web service schema, as shown in Figure 11-5.

Figure 11-5 Remote Service Schema File

Generated remote service schema

11.2.2.3 Remote Service Definition File

The remote service definition file is a XML-structured document file that conforms to the Web Service Definition Language (WSDL) specification that describes the generated web service as a collection of endpoints, or ports. A port is defined by associating a network address with a reusable binding. The client application that connects to the web service reads the WSDL to determine what functions are available on the server. The WSDL also specifies the endpoint for the service itself, which you can use to locate and test your deployed service.

Figure 11-6 shows the WSDL for the web service generated for the StoreServiceAM application module in the WSDL visual editor. You can see the WSDL as an XML document by selecting the Source tab.

Figure 11-6 WSDL Document

WSDL document in design view

11.2.2.4 Remote Server Class

The remote server class is an EJB 3.0 stateless session bean that implements the remote common interface and extends the ServiceImpl class, the generic service engine for ADF Business Components. Example 11-2 shows part of StoreFrontServiceImpl.java, which is the remote server class for the StoreServiceAM application module in the StoreFront module of the Fusion Order Demo.

Example 11-2 Remote Server Class Implements the Remote Common Interface

package oracle.fodemo.storefront.store.service.server.serviceinteface;
...
import oracle.fodemo.storefront.store.queries.common.CustomerInfoVOSDO;
import oracle.fodemo.storefront.store.queries.common.OrderInfoVOSDO;
import oracle.fodemo.storefront.store.service.common.serviceinterface.StoreFrontService;

...
import oracle.webservices.annotations.PortableWebService;
import weblogic.javaee.CallByReference;
...
@Stateless(name="oracle.fodemo.storefront.store.service.common.StoreFrontServiceBean")
@Remote(StoreFrontService.class)
@PortableWebService(targetNamespace="http://www.globalcompany.com/StoreFrontService", 
    serviceName="StoreFrontService", portName="StoreFrontServiceSoapHttpPort", 
    endpointInterface="oracle.fodemo.storefront.service.common.serviceinteface.StoreFrontService")
@CallByReference
public class StoreFrontServiceImpl extends ServiceImpl implements StoreFrontService 
{
    ...
    /**
     * findCustomerInfoVO1: generated method. Do not modify.
     * @param findCriteria
     * @param findControl
     * @return
     * @throws ServiceException
     */
    public List<CustomerInfoVOSDO> findCustomerInfoVO1(FindCriteria findCriteria,
                                           FindControl findControl) throws ServiceException {
        return (List<CustomerInfoVOSDO>)find(findCriteria, findControl,
                                             "CustomerInfoVO1",
                                             CustomerInfoVOSDO.class);
    }
...
}

11.2.2.5 connections.xml

The ADF Business Components service factory is the mechanism that allows the service client to look up the service. The service factory relies on ADF connection architecture and the connections.xml file to manage service endpoint locations. The connections.xml file is created when you first create an ADF Business Components service. This file appears in the Application Navigator in the Application Resources panel, under the Descriptors and ADF META-INF folders.

Example 11-3 shows the initial connections.xml entry created by JDeveloper when you first create an ADF Business Components service.

Example 11-3 connections.xml File Generated by JDeveloper

<Reference name="{http://www.globalcompany.com}StoreFrontService"
                    className="oracle.jbo.client.svc.Service" xmlns="">
   <Factory className="oracle.jbo.client.svc.ServiceFactory"/>
   <RefAddresses>
      <StringRefAddr addrType="serviceInterfaceName">
         <Contents>oracle.fodemo.storefront.store.service.common.serviceinterface.
                           StoreFrontService</Contents>
      </StringRefAddr>
      <StringRefAddr addrType="serviceEndpointProvider">
         <Contents>ADFBC</Contents>
      </StringRefAddr>
      <StringRefAddr addrType="jndiName">
         <Contents>oracle.fodemo.storefront.store.service.common.
                           StoreFrontServiceBean</Contents>
      </StringRefAddr>
      <StringRefAddr addrType="serviceSchemaName">
         <Contents>StoreFrontService.xsd</Contents>
      </StringRefAddr>
      <StringRefAddr addrType="serviceSchemaLocation">
         <Contents>oracle/fodemo/storefront/store/service/common/
                                     serviceinterface/</Contents>
      </StringRefAddr>
   </RefAddresses>
</Reference>

11.2.3 What You May Need to Know About Method Signatures on the Service Interface

You can define two different kinds of interfaces for an application module: the client interface and the service interface. The client interface is used by the ADF Model layer for UI clients. The service interface is for application integration and is used by external web services or other application services (either programmatically or automatically using the service-enabled entity feature).

An application module can support no interface at all, only client interfaces, only service interfaces, or both client interfaces and service interfaces combined. However, be aware that the two kinds of interfaces differ in the data types that are supported for the parameters and/or return values of your custom methods that you define for the respective interfaces. The types supported on the client interface are described in Section 9.9.5, "What You May Need to Know About Method Signatures on the Client Interface."

The service interface, in contrast to the client interface, supports a more narrow set of data types for custom method parameters and return values and is limited to:

  • Java primitive types and their object wrapper types (e.g. int, Integer)

  • java.lang.String

  • java.math.BigDecimal

  • java.math.BigInteger

  • java.sql.Date

  • java.sql.Time

  • java.sql.Timestamp

  • java.util.Date

  • oracle.jbo.AttributeList

  • oracle.jbo.domain.BlobDomain

  • oracle.jbo.domain.Char

  • oracle.jbo.domain.ClobDomain

  • oracle.jbo.domain.DBSequence

  • oracle.jbo.domain.Date

  • oracle.jbo.domain.NClobDomain

  • oracle.jbo.domain.Number

  • oracle.jbo.domain.Timestamp

  • oracle.jbo.domain.TimestampLTZ

  • oracle.jbo.domain.TimestampTZ

  • oracle.jbo.server.ViewRowImpl or any subtype

  • java.util.List<aType>, where aType is any of the service-interface supported data types

You can define a custom method that returns a type of AttributeList when you want the client developer to work with the list of service-enabled entity object or view object attributes to perform custom operations without the need to involve framework behavior before running the custom method. As an alternative, when the client developer wants the framework to manage rows (create, find, and populate), define custom methods that return ViewRowImpl instead. In summary, if your method signature defines ViewRowImpl as the data type, then the application automatically:

  1. Looks up the row in the corresponding view object instance by primary key and/or alternate key

  2. If the row is not found, then creates a new row

  3. Applies the attribute changes in the found or new row

Whereas, if your method signature defines the AttributeList data type, then no automatic behavior is provided, and the actions performed and data modified by the custom method will be limited to your custom method's code.

11.2.4 How to Service-Enable Individual View Objects

As a result of enabling the web service interface using the overview editor for the application module, JDeveloper automatically enables your parent view instance selections as Service Data Object (SDO) components. The generated SDO components for each view instance will reference the same namespace and will be configured with the same settings for options such as whether or not warnings are supported. You can use the Java page of the overview editor to customize the SDO definition of these existing service-enabled view objects. You can also use the Java page to service-enable view objects that were not added already to the service interface. For example, if you selected a parent view object that represents the master in a master-detail relationship, the child view object will not be automatically service-enabled. You can use the Java page of the overview editor for the child view object to individually add it to the service interface.

You use the Java page of the overview editor for the view object to configure the SDO name and namespace for a view object, or to selectively service-enable child view objects.

Before you begin:

Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.2.3, "How to Create an Expert Mode, Read-Only View Object."

To set the SDO name and namespace for a view object:

  1. In the Application Navigator, double-click the view object.

  2. In the overview editor, click the Java navigation tab and click the Edit java options button.

  3. In the Select Java Options dialog, in the Service Data Object section, select Generate Service Data Object Class. Enter a value for the service data object name and the service data object's target namespace.

    The target namespace is a URI for the SDO that you can assign to group similar SDOs together by entering the same URI.

    A default SDO namespace is created for you based on the SDO's package name with periods replaced by "/". If you have defined a prefix for the namespace in the View Objects page of the Preferences dialog, the prefix will be added at runtime to the beginning of the namespace. For example, Figure 11-7 shows the default namespace based on the package name.

    Figure 11-7 Service Data Object Name and Namespace Options

    Java dialog for a view object
  4. Optionally, select Support Warnings when you want to be able to extract warnings associated with the view rows of the service interface object.

  5. Click OK.

11.2.5 How to Customize the SDO Properties of Service-Enabled View Objects

You can use the overview editor for the view object to customize the SDO component definition of the service-enabled view object. By default, all attributes of the service-enabled view object will be exposed as SDO properties. By customizing the view object definition, you can exclude individual SDO properties from participating in the service interface. In the case of SDO properties that define numeric values, you can associate two properties so they appear as a single complex type in the service interface. For example, you can associate one property that defines a currency code or unit of measure with another property that displays the numeric value. Currently, only the complex service types AmountType (a currency code) and MeasureType (a unit of measure) are supported.

11.2.5.1 Excluding Individual SDO Properties in a Generated SDO Component

As a result of enabling the web service interface using the overview editor for the application module, JDeveloper automatically enables your parent view instance selections as SDO components. Additionally, you can selectively service-enable individual child view objects and generate SDO components. By default, generated SDO components expose all attributes of their base view object definition as SDO properties. You can hide any attribute that you do not want the service interface to return as an SDO property.

You use the Attributes page of the overview editor to select the view object attribute that you want to exclude from the service interface. You use the Edit Attribute dialog that you display from the Attributes page of the overview editor for the view object to hide the selected attribute from the SDO component.

Before you begin:

It may be helpful to have an understanding of how the SDO framework supports service-enabled ADF view objects and enables web service clients to access rows of data and perform service operations. For more information, see Section 11.2, "Publishing Service-Enabled Application Modules."

You will need to complete these tasks:

  1. Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.2.3, "How to Create an Expert Mode, Read-Only View Object."

  2. Service-enable the desired view object, as described in Section 11.2.4, "How to Service-Enable Individual View Objects."

To exclude an SDO property from a service-enabled view object:

  1. In the Application Navigator, double-click the view object.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the attribute corresponding to the property that you want to exclude, and then click the Edit selected attribute button.

  4. In the Edit Attribute dialog, in the View Attribute page, deselect SDO Property.

  5. Click OK.

11.2.5.2 Associating Related SDO Properties Using Complex Data Types

As a result of service-enabling the view object, JDeveloper automatically exposes SDO properties as XSD-defined service types that correspond to the data types of the underlying view object's attributes. In the case of attributes that define numeric values, you can change the SDO property's service type to associate a related property using one of these predefined service types:

  • AmountType service type, for use with any property that defines a currency code

  • MeasureType service type, for use with any property that defines a unit of measure

When you change the service type of an SDO property to either of these complex types, the service interface associates the two properties together and returns them as a single XML element. Both properties of the SDO component must be defined by attributes in the base service-enabled view object.

For example, suppose that your view object defines the OrderTotal attribute and a CurrencyCode attribute to specify the currency code of allowed countries. By default, the service interface exposes these attributes as SDO properties and returns each property as a separate XML element:

<OrderTotal>100.00</Price>
<CurrencyCode>USD</CurrencyCode>

If you change the type of the OrderTotal property (assume that the XSD file defines this property as a decimal type) to the complex type AmountType and then associate the CurrencyCode property, the service interface will return them as one XML element:

<OrderTotal CurrencyCode="USD">123.00</OrderTotal>

Also, when you generate a web service proxy, as described in Section 13.2.5.4, "Invoking Application Modules with a Web Service Proxy Class," the class treats the two values as one object:

AmountType price;
...
price.setValue(123.00);
price.setCurrencyCode("USD");

You use the Attributes page of the overview editor to select the view object attribute whose service type you want to customize. You use the Edit Attribute dialog that you display from the Attributes page of the overview editor to associate SDO properties for the selected attribute and select the predefined complex service type.

Before you begin:

It may be helpful to have an understanding of how the SDO framework supports service-enabled ADF view objects and enables web service clients to access rows of data and perform service operations. For more information, see Section 11.2, "Publishing Service-Enabled Application Modules."

Complete these tasks:

  1. Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.2.3, "How to Create an Expert Mode, Read-Only View Object."

  2. Service-enable the desired view object, as described in Section 11.2.4, "How to Service-Enable Individual View Objects."

To associate SDO properties in a service-enabled view object:

  1. In the Application Navigator, double-click the view object.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the attribute corresponding to the property that you will associate with another SDO property, and then click the Edit selected attribute button.

    The attribute you select must define a numeric type. For example, to associate a currency code with the attribute that displays the amount paid by a customer, you might select the OrderTotal attribute in the Orders service-enabled view object.

  4. In the Edit Attribute dialog, in the View Attribute page, choose the desired XSD Type.

    If the XSD Type field is not enabled, return to the overview editor and select an attribute of type numeric. Attributes whose values are not a numeric type cannot be associated with the available complex service types.

    The SDO framework supports the complex service types AmountType and MeasureType. Choose AmountType when the property you want to associate specifies currency information. Choose MeasureType when the property you want to associate specifies a unit of measure.

  5. In the currencyCode or unitCode dropdown list, select the view object attribute to define the complex type.

    The dialog changes to display the dropdown list appropriate to the XSD type selection. You can choose any numeric attribute that the view object defines.

  6. Click OK.

11.2.6 How to Support Nested Processing in Service-Enabled Master-Detail View Objects

When your data model defines master-detail relationships between parent and child view objects, the service operations that you enable for the master view object will not automatically be executed on the detail view object. You will need to enable support for nested processing for these methods in the service interface:

  • To support get and find methods that retrieve child details along with the parent, the view link between the master and detail view objects must have the destination accessor generated. The destination accessor permits traversal of the hierarchy from the master to the detail view object.

  • To support create/merge/update/process methods that post child details along with the parent, the custom property SERVICE_PROCESS_CHILDREN must be defined in one of these two situations:

    • The view link is based on an association, and the association has the destination accessor generated, and the association has a custom property SERVICE_PROCESS_CHILDREN=true defined.

    • The view link is not based on an association but has a custom property SERVICE_PROCESS_CHILDREN=true defined.

    Normally, post operations on the detail view object would only be supported when the primary entity object of the master view object is composed with the primary entity object of the detail view object. The custom property provides an alternative that makes it convenient to support nested processing for any view objects with a view link defined. You can define SERVICE_PROCESS_CHILDREN as a custom property in the overview editor for either the view link or the view link's association (when present).

Before you begin:

  1. Create the desired view objects and service-enable the child view object in the master-detail hierarchy, as described in Section 11.2.4, "How to Service-Enable Individual View Objects."

  2. If the view link is not based on an association, confirm that a destination accessor exists for the view link by opening the view link in the overview editor and viewing the Relationship page. To generate the accessor so it appears in the Relationship page, click the Edit Accessors button, and then, in the View Link Properties dialog, select Generate Accessor in View Object for the destination accessor. For more information about view links, see Section 5.6, "Working with Multiple Tables in a Master-Detail Hierarchy."

    If the view link is based on an association, then the destination accessor must be exist for the association's destination entity object. To generate one, use the Relationship page of the overview editor for the association. For more information about associations, see Section 4.3, "Creating and Configuring Associations."

To support nested processing in a master-detail hierarchy:

  1. If the view link for the master-detail hierarchy is not based on an association, then in the Application Navigator, double-click the view link; otherwise, if the view is based on an association, then in the Application Navigator, double-click the association.

    You can confirm how the view link was created in the Relationship page of the overview editor. The Attributes section names the source and destination attributes. When the view link is based on an association, the attribute hyperlinks will contain the names of the association. Otherwise, the hyperlinks will contain the names of the base entity objects.

  2. In the overview editor, click the General navigation tab.

    The overview editor for the view link and the association both display these same selections.

  3. In the General page, expand the Custom Properties section, and then click Add Custom Property and enter SERVICE_PROCESS_CHILDREN for the property and enter true for the property value, as shown in Figure 11-8.

    Figure 11-8 Custom Property to Support Nested Processing

    Custom Property to Support Nested Processing

11.2.7 What Happens When You Create SDO Classes

When you create SDO classes, the following files are generated and appear in the Application Navigator under the owning view object:

  • Service data object Interface

  • Service data object class

  • Service data object schema file

  • Service data object result class and Interface, generated when Support Warnings is enabled in the Select Java Options dialog

11.2.7.1 Service Data Object Interface

The view object SDO interface contains strongly typed accessors for the SDO properties, as shown in Example 11-4.

Example 11-4 SDO Interface Contains Strongly Typed Accessors for SDO Properties

package oracle.fodemo.storefront.store.queries.common;
  public interface AddressesVOSDO {
  public java.math.BigInteger getAddressId();
  public void setAddressId(java.math.BigInteger value);
...}

11.2.7.2 Service Data Object Class

The view object SDO class implements the view object SDO interface and extends the SDODataObject class, which is Oracle's implementation of the SDO specification.

At runtime an instance of an SDO object represents a row in memory.

The SDO class is similar to the view row class, as shown in Example 11-5.

Example 11-5 SDO Class Implements View Object SDO Interface

package oracle.fodemo.storefront.store.queries.common;
import commonj.sdo.Type;
import oracle.sdo.SDODataObject;
public class AddressesVOSDOImpl extends SDODataObject implements AddressesVOSDO 
  {
  ...
  }

11.2.7.3 Service Data Object Schema File

The view object SDO schema file, as shown in Figure 11-13, is an XML Schema file which represents the SDO schema.

Figure 11-9 Generated SDO Schema

Generated SDO schema in the Schema Editor

11.2.7.4 Service Data Object Result Class and Interface

The view object SDO result class is a container object that allows a service method to return a list of view rows (wrapped in service data objects) and a list of warnings associated with these view rows. You can use the generated method result interface to extract warnings and exceptions. Note that a service-enabled view object throws service exceptions rather than ADF Business Components exceptions (JboException object). To remedy this, the service interface adapter attempts to reconstitute ServiceException to JboException, where possible.

The view object SDO result class, as shown in Example 11-6, is similar to the view row class.

Example 11-6 SDO Result Class Defines Methods to Get Warnings from List

package oracle.fodemo.storefront.store.queries.common;
import oracle.sdo.SDODataObject;
public class OrderInfoVOSDOResultImpl extends 
   oracle.jbo.common.service.types.MethodResultImpl implements OrderInfoVOResult {

   public static final int START_PROPERTY_INDEX = 
          oracle.jbo.common.service.types.MethodResultImpl.END_PROPERTY_INDEX + 1;
   public static final int END_PROPERTY_INDEX = START_PROPERTY_INDEX + 0;
   public OrderInfoVOResultImpl() {}
   public java.util.List getValue() {
      return getList(START_PROPERTY_INDEX + 0);
   }

   public void setValue(java.util.List value) {
      set(START_PROPERTY_INDEX + 0 , value);
   }
}

11.2.8 How to Expose a Declarative Find Operation Filtered By a Required Bind Variable

The ADF service interface framework allows you to expose declarative find operations to execute the query define by a view object you select. However, when that query uses a bind variable to filter the query results, the bind variable must not be specified as Required and Updatable. Because the service interface does not expose required, updatable bind variables, a find operation that you execute for such a view object would fail to return any result.

When you want to filter a query result using bind parameters, use the view criteria and expose it as a find operation on the service interface. A service interface find operation based on a view criteria that you create can specify required bind variables.

Before you begin:

  1. Create the desired application module as described in Section 9.2.1, "How to Create an Application Module."

  2. Create the view criteria as described in Section 5.11.1, "How to Create Named View Criteria Declaratively." In the Edit View Criteria dialog, set the criteria item as a bind variable and set the Validation field to Required. This selection ensures that the query will not execute without a valid value.

To expose a find operation for a view criteria with required bind variable:

  1. In the Application Navigator, double-click the application module.

  2. In the overview editor, click the Service Interface navigation tab and click the Edit attributes of Service Interface button.

    Alternatively, you can select Edit Service Custom Methods if you have already defined the service interface.

  3. In the Edit Service Interface dialog, select Service View Instances from the navigation list and add the view object that you want to filter with its named view criteria to the Selected list.

  4. To expose the find operation, select the view instance, click the View Criteria Find Operations tab, and then click the Add View Criteria button.

  5. In the Configure View Criteria Find Operation dialog, choose the named view criteria for the find operation.

    The dialog displays the bind variable for the selected view criteria.

  6. You can double-click the XML name to customize the bind variable name shown in the XML definition for the service.

  7. Click OK.

11.2.9 How to Expose a Custom Find Method Filtered By a Required Bind Variable

As an alternative to exposing a declarative find operation that relies on a view criteria, you can define a service method in your data model project's application module implementation class. The class you create for this purpose allows you to encapsulate business service functionality into a single method that you implement. For details about the purpose of the custom application module implementation class, see Section 9.7, "Customizing an Application Module with Service Methods."

Example 11-7 shows a custom find method implemented in the AppModuleNameImpl.java file to set the bind variable and execute the view object instance query. It uses setNamedWhereClauseParam() on the view object instance to set the bind variable. Before executing the query, the find method sets the view object in forward-only mode to prevent caching the view rows that the find method iterates over. For more information about programmatically filtering a query result, see Section 5.10.5, "How to Add a WHERE Clause with Named Bind Variables at Runtime."

Example 11-7 Find Method Added to Application Module Implementation Class

public class AppModuleImpl extends ApplicationModuleImpl
{
   public List<ViewRowImpl> findProducts(String location)
   {
      List<ViewRowImpl> result = new ArrayList<ViewRowImpl>();
      ViewObjectImpl vo = getProductsView1();
      vo.setNamedWhereClauseParam("TheLocation", location);
      vo.setForwardOnly(true);
      vo.executeQuery();
      while (vo.hasNext()) {
        result.add((ViewRowImpl)vo.next());
      }
      return result;
   }
}

Before you begin:

Create the custom application module class as described in Section 9.7.1, "How to Generate a Custom Class for an Application Module."

To expose a find method that sets a required bind variable:

  1. In the Application Navigator, double-click the application module.

  2. In the overview editor, click the Service Interface navigation tab and click the Edit attributes of Service Interface button.

    Alternatively, you can select Edit Service Custom Methods if you have already defined the service interface.

  3. In the Edit Service Interface dialog, select Service View Instances from the navigation list and add the view object that you want to filter with its named view criteria to the Selected list.

  4. To expose the find operation, select the view instance and select the View Criteria Find Operations tab and then click the Add View Criteria icon.

  5. Click OK.

11.2.10 How to Generate Asynchronous Web Service Methods

By default, the web service supports synchronous service methods. This forces the invoking client application to wait for the response to return before it can continue with its work. In cases where the response returns immediately, this method of invoking the web service is common. However, because request processing can be delayed, it is often useful for the client application to continue its work and to handle the response later on.

For more information about invoking the web service using asynchronous request-response, see Oracle Fusion Middleware Concepts Guide for Oracle Infrastructure Web Services.

Before you can deploy an asynchronous web service, you must configure the queues used to store the request and response. For information about configuring the request and response queues, see the Oracle Fusion Middleware Concepts Guide for Oracle Infrastructure Web Services.

Before you begin:

Create the desired application module as described in Section 9.2.1, "How to Create an Application Module."

To expose asynchronous web service methods:

  1. In the Application Navigator, double-click the application module.

  2. In the overview editor, click the Service Interface navigation tab and click the Edit attributes of Service Interface button.

  3. In the Edit Service Interface dialog, select Generate Asynchronous Web Service Methods.

  4. Click OK.

11.2.11 What Happens When You Generate Asynchronous Service Methods

JDeveloper generates the remote common interface for the service and enables the asynchronous service operation. As shown in Example 11-8, the class annotation @AsyncWebService declares the EmpService service interface asynchronous and for each synchronous method in the interface, the service exposes an asynchronous method with the same method name and "Async" appended.

Exposing both synchronous and asynchronous methods in the same interface allows the web service client developer to decide how to invoke the operation through a web service proxy: by calling the appropriately named method. Note that developers should not invoke asynchronous methods through the ADF Business Components service proxy directly.

In this example, because the EmpService service is enabled for asynchronous operation, the interface exposes the getEmployeeAsync() method and declares the getEmployee() method synchronous using the method annotation @CallbackMethod(exclude=true) to override the default operation (it is the exclude=true part that declares a method in the asynchronous service as synchronous). No annotation is required to declare the asynchronous service methods when the class annotation @AsyncWebService is present.

Example 11-8 Remote Common Interface with Asynchronous Service Methods

import javax.xml.ws.Action;
...
import oracle.webservices.annotations.async.AsyncWebService;
import oracle.webservices.annotations.async.CallbackMethod;

@SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.WRAPPED, style=SOAPBinding.Style.DOCUMENT)
@PortableWebService(targetNamespace="http://xmlns.example.com/apps/service/", name="EmpService",
                    wsdlLocation="oracle/apps/service/EmpService.wsdl")
@SDODatabinding(schemaLocation="oracle/apps/service/EmpService.xsd")
@AsyncWebService
public interface EmpService
{
   ...

   @WebMethod(action="http://xmlns.example.com/apps/service/getEmployee",
                       operationName="getEmployee")
   @RequestWrapper(targetNamespace="http://xmlns.example.com/apps/service/types/",
                       localName="getEmployee")
   @ResponseWrapper(targetNamespace="http://xmlns.example.com/apps/service/types/",
                       localName="getEmployeeResponse")
   @WebResult(name="result")
   @CallbackMethod(exclude=true)
   Emp getEmployee(@WebParam(mode = WebParam.Mode.IN, name="empno") Integer empno)
      throws ServiceException;
 
   @WebMethod(action="http://xmlns.example.com/apps/service/getEmployeeAsync",
                        operationName="getEmployeeAsync")
   @RequestWrapper(targetNamespace="http://xmlns.example.com/apps/service/types/",
                        localName="getEmployeeAsync")
   @ResponseWrapper(targetNamespace="http://xmlns.example.com/apps/service/types/",
                        localName="getEmployeeAsyncResponse")
   @WebResult(name="result")
   @Action(input="http://xmlns.example.com/apps/service/getEmployeeAsync",
           output="http://xmlns.example.com/apps/service/getEmployeeAsyncResponse")
   Emp getEmployeeAsync(@WebParam(mode = WebParam.Mode.IN, name="empno") Integer empno);
}

The duplicate asynchronous methods delegate to the synchronous methods in the service implementation, as shown in Example 11-9. This ensures that the underlying business logic is the same for operations declared as either synchronous or asynchronous.

Example 11-9 Remote Server Class Implements Asynchronous Service Methods

...
import oracle.webservices.annotations.async.AsyncWebService;

@Stateless(name="oracle.apps.service.EmpServiceBean", mappedName="EmpServiceBean")
@Remote(EmpService.class)
@PortableWebService(targetNamespace="http://xmlns.oracle.com/apps/service/",
                     serviceName="EmpService", portName="EmpServiceSoapHttpPort",
                     endpointInterface="oracle.apps.service.EmpService")
@Interceptors(ServiceContextInterceptor.class)
@AsyncWebService
public class EmpServiceImpl extends ServiceImpl implements EmpService
{
   ...

   /**
    * getEmployee: generated method. Do not modify.
    */
   public Emp getEmployee(Integer empno)
      throws ServiceException
   {
      return (Emp) get(new Object[] { empno }, "Employee", Emp.class);
   }

   /**
    * getEmployeeAsync: generated method. Do not modify.
    */
   public Emp getEmployeeAsync(Integer empno)
      throws ServiceException
   {
      return getEmployee(empno);
   }
}

11.2.12 What Happens at Runtime: When the Asynchronous Call Is Made

From the client's point of view, an asynchronous call consists of two one-way message exchanges. The sequence diagram in Figure 11-10 depicts the following flow:

  1. The client calls for the asynchronous operation. (In the figure, Step 1.)

  2. The asynchronous service receives the request and returns the HTTP acknowledgement back to the client without actually processing the request. (In the figure, step 2)

  3. Eventually the asynchronous operation will complete and the module on the server side will send the response to the client side. (In the figure, step 3.)

    To receive the response at the client side, the client must have some kind of HTTP listener, for example, a servlet or a web service.

  4. The client side-generated web service (the Callback Service) receives the asynchronous responses. (In the figure, step 4.)

    The module in step 3 on the server side acts like a client to the callback service and so is referred as the callback client.

Figure 11-10 Asynchronous Call Sequence

Asynchronous Call Sequence

11.2.13 How to Set Preferences for Generating the Service Interface

You have additional control of the service generated by JDeveloper. You can set JDeveloper preferences to use a default suffix for the names of generated SDO classes, modifying the default subpackage where the service common interface and classes go.

To set the SDO class name suffix:

  1. From the main menu, choose Tools > Preferences.

  2. In the Preferences dialog, expand the Business Components node and choose Class Naming.

  3. In the View Object suffix list, enter a suffix for SDO, for example, SDO.

To set the default subpackage for the generated service interface:

  1. From the main menu, choose Tools > Preferences.

  2. In the Preferences dialog, expand ADF Business Components and choose Packages.

  3. In the Relative Package Specification for Classes list, specify the default package names:

    • To set the Service Interface package name, enter a value for the Client Interface. (The Service Interface displays the same package name you specify for the client interface). The default package name is common.

    • Enter a value for the Service Interface Subpackage of the Service Interface. The default subpackage name is serviceinterface.

    For example, if you enter common for Service Interface and serviceinterface for Service Interface Subpackage (the defaults), service interfaces for data model components in the data model package oracle.storefront.store.service will be placed in the subpackage oracle.storefront.store.service.common.serviceinterface.

To set the default namespace prefix for the generated SDO schema and web service:

  1. From the main menu, choose Tools > Preferences.

  2. In the Preferences dialog, expand the Business Components node and choose View Objects.

  3. Enter a value for the Service Data Object Namespace Prefix to be added to the beginning of the target namespace of the generated SDO schema and web service. For example, http://example.com/.

11.2.14 How to Secure the Web Service for SOAP Clients

At runtime, the web service client will invoke the service-enable methods of the application module through the SOAP protocol. You can configure a Oracle Web Service Manager (Oracle WSM) security policy to enable authentication and authorization on the service. The security policy that you select will require the SOAP client call to provide credential information (or SAML token) as part of the SOAP header. You can also configure other policies to enable message protection (integrity and confidentiality) for inbound SOAP requests, for instance. For information about the predefined policies supported by Oracle WSM, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.

11.2.14.1 Enabling Authentication for SOAP Clients

You can enable authentication to require users to supply credentials before they have access to the service methods on the service interface. The type of authentication required is configured on the remote server class using an Oracle WSM authentication policy. For details about the available authentication policies, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.

To configure an authentication policy:

  1. In the Application Navigator, expand the application module, expand the serviceinterface folder, and then double-click the remote server class (AppModuleServiceImpl.java file).

    In the web service generated from the StoreServiceAM application module in the StoreFrontModule application of the Fusion Order Demo, the remote server class is StoreFrontServiceImpl.java.

  2. In the source for the remote server class, place your cursor on the @PortableWebService annotation.

    For example, StoreFrontService.wsdl shows the annotation for the service as follows:

    ...
    @PortableWebService(targetNamespace="www.globalcompany.example.com",
        serviceName="StoreFrontService", portName="StoreFrontServiceSoapHttpPort",    endpointInterface=
           "oracle.fodemo.storefront...common.serviceinterface.StoreFrontService")
    ...
    
  3. Open the Property Inspector and expand the Web Services Extension section, and then click the ellipsis button next to the Security field for Oracle WSM Policies.

  4. In the Edit Property: Security dialog, select the desired authentication security policy and click OK.

    For details about the available security policies supported by Oracle WSM, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.

  5. Return to the source file and note that new annotation @SecurityPolicy has been added.

    The @SecurityPolicy annotation that you define for the remote server class specifies the security requirements to potential clients. For example, if you had selected oracle/wss_username_token_service_policy in the dialog, the following @SecurityPolicy annotation would appear below the @PortableWebService annotation:

    ...
    @PortableWebService(targetNamespace="www.globalcompany.example.com",
        serviceName="StoreFrontService", 
        portName="StoreFrontServiceSoapHttpPort",    endpointInterface=
        "oracle.fodemo.storefront.store.service.common.serviceinterface.StoreFrontService")
    @SecurityPolicy( { "oracle/wss_username_token_service_policy" })
    ...
    

    For details about configuring an authorization policy to require users to have sufficient access rights in order to invoke methods on the service, see Section 11.2.14.2, "Enabling Authorization for SOAP Clients."

  6. Save the remote server class file.

11.2.14.2 Enabling Authorization for SOAP Clients

You can enable permission checking to enable only users with sufficient privileges to invoke a service method on the service interface. This permission checking is configured on the remote server class using this Oracle Web Services Manager (Oracle WSM) authorization policy:

  • binding_permission_authorization_policy

    This policy provides simple permission-based authorization for the request based on the authenticated Subject at the SOAP binding level. This policy ensures that the Subject has permission to perform the operation. This policy should follow an authentication policy where the Subject is established and can be attached to any SOAP-based endpoint.

As an alternative to the permission checking policy, you can configure one of these role-based Oracle WSM security policies:

  • binding_authorization_denyall_policy

    This policy provides simple role-based authorization for the request based on the authenticated Subject at the SOAP binding level. This policy denies all users with any roles. It should follow an authentication policy where the Subject is established and can be attached to any SOAP-based endpoint.

  • binding_authorization_permitall_policy

    This policy provides a simple role-based authorization for the request based on the authenticated Subject at the SOAP binding level. This policy permits all users with any roles. It should follow an authentication policy where the Subject is established and can be attached to any SOAP-based endpoint.

For further details about these authorization policy, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.

Before you begin:

  1. Configure an authentication policy for the service, as described in Section 11.2.14.1, "Enabling Authentication for SOAP Clients."

  2. Grant users access to the service, as described in Section 11.2.16, "How to Grant Test Users Access to the Service."

To configure a permission-based authorization policy:

  1. In the Application Navigator, expand the application module, expand the serviceinterface folder, and then double-click the remote server class (AppModuleServiceImpl.java file).

    In the web service generated from the StoreServiceAM application module in the StoreFrontModule application of the Fusion Order Demo, the remote server class is StoreFrontServiceImpl.java.

  2. In the source for the remote server class, place your cursor on the @PortableWebService annotation.

    For example, StoreFrontService.wsdl shows the annotation for the service as follows:

    ...
    @PortableWebService(targetNamespace="www.globalcompany.example.com",
        serviceName="StoreFrontService", 
        portName="StoreFrontServiceSoapHttpPort",
        endpointInterface=
           "oracle.fodemo.storefront...common.serviceinterface.StoreFrontService")
    ...
    
  3. Open the Property Inspector and expand the Web Services Extension section, and then click the ellipsis button next to the Security field for Oracle WSM Policies.

  4. In the Edit Property: Security dialog, select the desired security policy and click OK.

    For details about the security policies supported by Oracle WSM, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.

  5. Return to the source file and note that annotation @SecurityPolicy is configured.

    The @SecurityPolicy annotation that you define for the remote server class specifies the security requirements to potential clients. In this example, the annotation shows both the permission-checking authorization policy (oracle/binding_permission_authorization_policy) and an authentication policy:

    ...
    @PortableWebService(targetNamespace="www.globalcompany.example.com",
        serviceName="StoreFrontService", portName="StoreFrontServiceSoapHttpPort",
        endpointInterface=
           "oracle.fodemo.storefront...common.serviceinterface.StoreFrontService")
    @SecurityPolicy( { "oracle/binding_permission_authorization_policy",
                         "oracle/wss_username_token_service_policy" })
    ...
    

    For details about configuring an authentication policy to require the client to supply credentials in order to access the service, see Section 11.2.14.1, "Enabling Authentication for SOAP Clients."

  6. Save the remote server class file.

11.2.15 How to Secure the Web Service for RMI Clients

Because the ADF web service is implemented as an EJB and deployed on Oracle WebLogic Server as Oracle Web Service's PortableWebService, the client application can invoke the service-enable methods of the application module through the RMI protocol.

11.2.15.1 Enabling Authentication for RMI Clients

When the ADF service is invoked through RMI, authentication is handled with the common JAAS login module. The login module can be passed the principal and credential as part of the JNDI initial context for the EJB in the calling application. If you do not define the JNDI context properties, the login module will attempt to obtain the caller's current security context.

When you choose to define remote JNDI context information, then these four JNDI context properties need to be added to the connections.xml file.

Note:

When you intend to test the service in JDeveloper using Integrated WebLogic Server, before deploying the service you can edit the JNDI context properties in the connections.xml file directly. However, when you deploy the service to standalone Oracle WebLogic Server, you will use Oracle Enterprise Manager to configure the JNDI context properties.
  • jndiFactoryInitial should be set to weblogic.jndi.WLInitialContextFactory.

  • jndiProviderURL is the JNDI provider URL that indicates the location of the JNDI server. The URL should be composed as t3://<hostname>:<server port>.

    When you test the service in JDeveloper, and your service is deployed to Integrated WebLogic Server, specify the JNDI provider URL of Integrated WebLogic Server: t3://<hostname>:7101.

    When you deploy the service to remote Oracle WebLogic Server, specify a URL like: t3://localhost:8888, where t3 is the Oracle WebLogic protocol, localhost is the host name that the remote Oracle WebLogic Server instance runs in, 8888 is the port number.

  • jndiSecurityPrincipal specifies the principal (user name) with permission to access the remote JNDI.

    As Example 11-10 shows, when you test the service in JDeveloper Integrated WebLogic Server, you should omit this context property since no security is configured for the JNDI server on Integrated WebLogic Server.

    As Example 11-11 and Example 11-12 show, when you deploy the service to standalone Oracle WebLogic Server, the user name can be read from the file.

  • jndiSecurityCredentials specifies the credentials (password) to be used for the security principal.

    As Example 11-10 shows, when you test the service in JDeveloper Integrated WebLogic Server, you should omit this context property since no security is configured for the JNDI server on Integrated WebLogic Server.

    As Example 11-11 shows, when you deploy the service to standalone Oracle WebLogic Server in a test environment, you can specify credentials in plain text for the JNDI provider. For example, you can specify weblogic/weblogic1 which are the default administrator user name/password credentials with sufficient privileges to access JNDI provider for Oracle WebLogic Server.

    When you deploy the service to a production environment, you must remove the plain text password to avoid creating a security vulnerability. As Example 11-12 shows, the connections.xml file must contain <SecureRefAddr addrType="jndiSecurityCredentials"/> with no password. To configure the service password for standalone Oracle WebLogic Server, you must use Oracle Enterprise Manager, which will store the encrypted password in Oracle's credential store.

To configure JNDI context properties to handle authentication:

  1. In the Application Navigator in the Application Resources panel, expand the Descriptors and ADF META-INF folders, and then double-click the connections.xml file.

  2. If the source editor, use the JNDI context properties to specify the principal and credentials.

    If you are testing the service in JDeveloper's Integrated WebLogic Server, you only need to specify the jndiProviderURL property, as shown in Example 11-10.

    Example 11-10 JNDI Properties for JDeveloper Integrated WebLogic Server

    <References xmlns="http://xmlns.oracle.com/adf/jndi">
      <Reference name="{www.globalcompany.com}StoreFrontService" 
                 className="oracle.jbo.client.svc.Service" xmlns="">
         <Factory className="oracle.jbo.client.svc.ServiceFactory"/>
         <RefAddresses>
           ...
           <StringRefAddr addrType="jndiFactoryInitial">
              <Contents>weblogic.jndi.WLInitialContextFactory</Contents>
           </StringRefAddr>
           <StringRefAddr addrType="jndiProviderURL">
               <Contents>t3://a_hostname:7101</Contents>
           </StringRefAddr>
           ...
         </RefAddresses>
      </Reference>
      ...
    </References>
    

    If you are deploying the service for testing purposes to standalone Oracle WebLogic Server, you can use the connections.xml file to specify credentials for the JNDI provider. For example, as shown in Example 11-11, you can specify weblogic/weblogic1 which are the default administrator user name/password credentials with sufficient privileges to access JNDI provider for Oracle WebLogic Server.

    Example 11-11 JNDI Properties for a Test Environment

    <References xmlns="http://xmlns.oracle.com/adf/jndi">
      <Reference name="{www.globalcompany.com}StoreFrontService" 
                 className="oracle.jbo.client.svc.Service" xmlns="">
         <Factory className="oracle.jbo.client.svc.ServiceFactory"/>
         <RefAddresses>
           ...
           <StringRefAddr addrType="jndiFactoryInitial">
              <Contents>weblogic.jndi.WLInitialContextFactory</Contents>
           </StringRefAddr>
           <StringRefAddr addrType="jndiProviderURL">
               <Contents>t3://localhost:8888</Contents>
           </StringRefAddr>
           <StringRefAddr addrType="jndiSecurityPrincipal">
               <Contents>welcome</Contents>
           </StringRefAddr>
           <SecureRefAddr addrType="jndiSecurityCredentials">
               <Contents>weblogic1</Contents>
           </SecureRefAddr>
           ...
         </RefAddresses>
      </Reference>
      ...
    </References>
    

    If you are deploying the service to production Oracle WebLogic Server, you can use the connections.xml file to specify the user name. As shown in Example 11-12, you must not specify the password.

    Example 11-12 JNDI Properties for a Production Environment

    <References xmlns="http://xmlns.oracle.com/adf/jndi">
      <Reference name="{www.globalcompany.com}StoreFrontService" 
                 className="oracle.jbo.client.svc.Service" xmlns="">
         <Factory className="oracle.jbo.client.svc.ServiceFactory"/>
         <RefAddresses>
           ...
           <StringRefAddr addrType="jndiFactoryInitial">
              <Contents>weblogic.jndi.WLInitialContextFactory</Contents>
           </StringRefAddr>
           <StringRefAddr addrType="jndiProviderURL">
               <Contents>t3://localhost:8888</Contents>
           </StringRefAddr>
           <StringRefAddr addrType="jndiSecurityPrincipal">
               <Contents>a_username</Contents>
           </StringRefAddr>
           <SecureRefAddr addrType="jndiSecurityCredentials/">
           ...
         </RefAddresses>
      </Reference>
      ...
    </References>
    
  3. Save the file.

11.2.15.2 Enabling Authorization for RMI Clients

You can enable permission checking to enable only users with sufficient privileges to invoke a service method on the service interface. In order enable permission checking, the ADF web service framework provides an EJB interceptor named ServicePermissionCheckInterceptor. This EJB interceptor ensures permission checking is enforced at runtime. Currently, the interceptor is configured to use the Oracle Web Services Manager (Oracle WSM) authorization policy binding_permission_authorization_policy. For further details about this authorization policy, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.

Before you begin:

  1. Configure the authentication policy for the service in the connections.xml file of the client application (the one invoking the service), as described in Section 11.2.15.1, "Enabling Authentication for RMI Clients."

  2. Grant users access to the service, as described in Section 11.2.16, "How to Grant Test Users Access to the Service."

To configure a permission-based authorization policy:

  1. In the Application Navigator, expand the META-INF folder of the web service project and double-click the ejb-jar.xml file.

  2. In the source editor, add the following JpsInterceptor definition required by the EJB for application roles evaluation.

    <?xml version = '1.0' encoding = 'windows-1252'?>
    <ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
             http://java.sun.com/xml/ns/j2ee/ejb-jar_3_0.xsd" version="3.0" 
             xmlns="http://java.sun.com/xml/ns/javaee">
      <enterprise-beans>
        ...
      </enterprise-beans>
      <interceptors>
         <interceptor>
            <interceptor-class>
                oracle.security.jps.ee.ejb.JpsInterceptor
            </interceptor-class>
               <env-entry>
                  <env-entry-name>application.name</env-entry-name>
                  <env-entry-type>java.lang.String</env-entry-type>
                  <env-entry-value>ApplicationName</env-entry-value>
                  <injection-target>
                      <injection-target-class>
                          oracle.security.jps.ee.ejb.JpsInterceptor
                      </injection-target-class>
                      <injection-target-name>
                          application_name
                      </injection-target-name>
                  </injection-target>
               </env-entry>
         </interceptor>
         ...
      <interceptors>
      <assembly-descriptor>
         <interceptor-binding>
            <ejb-name>*</ejb-name>
            <interceptor-class>
                 oracle.security.jps.ee.ejb.JpsInterceptor
            </interceptor-class>
         </interceptor-binding>
      </assembly-descriptor>
    </ejb-jar>
    
  3. In the Application Navigator, expand the application module, expand the serviceinterface folder, and then double-click the remote server class (AppModuleServiceImpl.java) file.

  4. In the source editor, place your cursor at the end of your annotations section and add the annotation named ServicePermissionCheckInterceptor to enable permission checking at runtime.

    ...
    @Stateless(name="oracle.fodemo.storefront.store.service.common.
                                              StoreFrontServiceBean")
    @Remote(StoreFrontService.class)
    @PortableWebService(targetNamespace="http://www.globalcompany.com/
                           StoreFrontService", serviceName="StoreFrontService",
                           portName="StoreFrontServiceSoapHttpPort", 
                           endpointInterface="oracle.fodemo.storefront.
                                 service.common.serviceinteface.StoreFrontService")
    @CallByReference
    @Interceptors({ServiceContextInterceptor.class,
                            ServicePermissionCheckInterceptor.class})
    
  5. Save the files.

11.2.16 How to Grant Test Users Access to the Service

After you have have configured the authorization policy for the service, you must configure the Oracle Platform Security Services (OPSS) security provider to specify which users can invoke method on the service. At design time, you perform this task by editing the jazn-data.xml configuration file to create application roles and make an invoke permission grant to the desired application roles. Then when you deploy the service, the administrator for the target Oracle WebLogic Server will associate enterprise users with the application roles you specify. This allows you to confer the right to invoke a service method to any user who is a member of that application role. Users who are members of a role that has not been granted the invoke permission, will denied access to the service method. For more information about the OPSS security provider and application roles, see the Oracle Fusion Middleware Security Guide.

To configure the jazn-data.xml file with test users that you can use to run the application in Integrated WebLogic Server, see Section 30.6, "Creating Test Users."

The invoke permission for Oracle Web Services is defined by the oracle.wsm.security.WSFunctionPermission class. You can grant the invoke permission to the application roles you define for all the methods of the service or just to individual methods.

Before you begin:

  1. Configure authentication and authorization policies for your service, as described in Section 11.2.14, "How to Secure the Web Service for SOAP Clients," or Section 11.2.15, "How to Secure the Web Service for RMI Clients."

  2. Add the OPSS security provider configuration file to your project by creating a jazn-data.xml deployment descriptor as described in "Creating and Editing a Deployment Descriptor" in the Deploying Applications section of the JDeveloper online help.

    Note that in JDeveloper you open the New Gallery, expand General, select Deployment Descriptors and then Oracle Deployment Descriptors, and click OK.

  3. Create the desired application roles, as described in Section 30.4, "Creating Application Roles."

  4. For the purpose of testing your web service in JDeveloper, you can populate the application roles with test users, as described in Section 30.6, "Creating Test Users."

To grant the web service permission to application roles in the jazn-data.xml file:

  1. From the Application menu, choose Secure > ADF Policies.

    Before you begin this procedure, you need to create the application roles that you want to make grants to, as described in Section 30.4, "Creating Application Roles." If you are testing in JDeveloper, you can also populate the application roles with test users, as described in Section 30.6, "Creating Test Users."

  2. In the editor window for the jazn-data.xml file, select the Source tab.

  3. In the source for the jazn-data.xml file, expand the <policy-store> element to view all ADF security policies that you already defined for your application.

    Currently, this release does not provide an editor to create an application security policy; you will need to manually create the policy in the source for the jazn-data.xml file.

  4. Inside the <jazn-policy> element, create a <grant> element that defines the <grantee> with the desired application role and the <permission> with the fully qualified class name of the Oracle WSM permission class (oracle.wsm.security.WSFunctionPermission), the permission target name that uniquely identifies the service method, and the invoke method action that you want to grant to the application role principal.

    Your finished source should look similar to this:

    <grant>
      <grantee>
        <principals>
          <principal>
             <class>oracle.security.jps.service.policystore.ApplicationRole</class>
             <name>customers</name>
          </principal>
         </principals>
      </grantee>
      <permissions>
         <permission>
           <class>oracle.wsm.security.WSFunctionPermission</class>
          <name>www.globalcompany.example.com/
                                           StoreFrontService#CreateAccount</name>
           <actions>invoke</actions>
         </permission>
       </permissions>
    </grant>
    

    The <principal> element is defined by the application role class name oracle.security.jps.service.policystore.ApplicationRole and an application role name that you already created. For example, if you created an application role customers and you want to grant invoke service method permission to the members of that role, then enter customers.

    The <permission> element is defined by the Oracle WSM class name oracle.wsm.security.WSFunctionPermission and the permission target name. The permission target name is formed by appending /serviceInterfaceName and #serviceMethodName (or wildcard character) to the service target namespace.

    Tip:

    You can find the target namespace and service name from the WSDL definition file for the service. In the Application Navigator, double-click the WSDL file in the serviceinterface folder to view the name and targetNamespace definitions.

    For example, in the Fusion Order Demo, the WSDL definition file defines the following name and namespace:

    <wsdl:definitions
         name="StoreFrontService"
         targetNamespace="www.globalcompany.example.com"
    

    Assume that you want to grant a permission to allow authorized users to invoke a CreateAccount service method on the service interface with these Fusion Order Demo name and namespace, you would enter the target name like this:

    www.globalcompany.example.com/StoreFrontService#CreateAccount
    

    Alternatively, you can enter the target name using the wildcard character * to grant all operations of the service interface in a single permission:

    www.globalcompany.example.com/StoreFrontService#*
    

    The actions that you can enter are defined by the permission class. In this case, oracle.wsm.security.WSFunctionPermission defines the single action invoke.

  5. Save the changes to the jazn-data.xml file.

11.2.17 How to Enable Support for Binary Attachments for SOAP Clients

The ADF service interface framework supports using Message Transmission Optimization Mechanism (MTOM) to handle sending binary data in any service method that operates on a ViewRow with a BlobDomain/ClobDomain attribute. This permits binary data to accompany XML messages, for example when images are required to document an insurance claim. The SDO data objects of the service-enabled application module maps BlobDomain/ClobDomain to javax.activation.DataHandler. These DataHandler properties could be passed as attachments during SDO data object marshalling/unmarshalling when the web service is called using the SOAP protocol.

To enable MTOM support for your SOAP protocol, you must add the @MTOM annotation to the service interface implementation class (for example, StoreFrontServiceImpl.java) and your method must operate on a ViewRow with BlobDomain/ClobDomain attribute.

To enable support for sending binary data attachments:

  1. In the Application Navigator, expand the application module, expand the serviceinterface folder, and then double-click the remote server class (AppModuleServiceImpl.java) file.

    In the web service generated from the StoreServiceAM application module in the StoreFrontModule application of the Fusion Order Demo, the remote server class is StoreFrontServiceImpl.java.

  2. In the source for the remote server class, place your cursor anywhere in the annotation section.

    For example, in the StoreFrontServiceImpl.java the annotation section for the service is:

    ...
    @Stateless(name="oracle.fodemo.storefront....common.StoreFrontServiceBean",
        mappedName="StoreFrontServiceBean")
    @Remote(StoreFrontService.class)
    @PortableWebService(targetNamespace="www.globalcompany.example.com",
        serviceName="StoreFrontService", portName="StoreFrontServiceSoapHttpPort",
        endpointInterface=
           "oracle.fodemo.storefront...common.serviceinterface.StoreFrontService")
    ...
    
  3. Open the Property Inspector and expand the Web Services section, then select Enable MTOM.

    JDeveloper adds the @MTOM annotation to the annotations section of the file.

    ...
    @Stateless(name="oracle.fodemo.storefront....common.StoreFrontServiceBean",
        mappedName="StoreFrontServiceBean")
    @Remote(StoreFrontService.class)
    @PortableWebService(targetNamespace="www.globalcompany.example.com",
        serviceName="StoreFrontService", portName="StoreFrontServiceSoapHttpPort",
        endpointInterface=
           "oracle.fodemo.storefront...common.serviceinterface.StoreFrontService")
    @MTOM
    ...
    

11.2.18 How to Test the Web Service Using Integrated WebLogic Server

You can run the web service in JDeveloper using Integrated WebLogic Server. You can also deploy the web service to Oracle WebLogic Server to test the service.

To run and test using Integrated WebLogic Server:

  1. In the Application Navigator, expand the application module, expand the serviceinterface folder, and then select the remote server class (AppModuleServiceImpl.java) file.

    In the web service generated from the StoreServiceAM application module in the StoreFrontModule application of the Fusion Order Demo, the remote server class is StoreFrontServiceImpl.java.

  2. Right-click the remote server class file, and choose Run or Debug.

    JDeveloper initializes the server instance, and then deploys the application and starts the web service. During this time, the output from these processes is displayed in the Running tab of the Log window. After the web service has started, the target URL is also displayed in the Log window.

  3. Copy the target URL (beginning with http://) from the Log window.

  4. Launch a web browser, paste the endpoint URL you copied from the Log window into the browser address field, append the service name, and submit the HTTP request.

    For example, if the Log window displays:

    http://130.35.103.93:8888/ADFServiceDemo-ADFModel-context-root

    and the name of the service is AppModuleService, the target URL would look like this:

    http://130.35.103.93:8888/ADFServiceDemo-ADFModel-context-root/AppModuleService

  5. In the test page, choose the operation you want to invoke from the Operations dropdown menu and enter sample data in its parameter fields.

  6. When you are ready, press Invoke to submit the operation and view the results for the operation in the Test Results page.

    The Test Results page displays the XML Soap format of the information returned by the operation.

11.2.19 How to Prevent Custom Service Methods from Timing Out

When you test the web service you may find that some of your custom methods exceed the established timeout limitation established by the Java Transaction API (JTA). The JTA timeout setting establishes an execution boundary for service methods that by default may not exceed 30 seconds. You could use the Administration Console for Oracle WebLogic Server to increase the JTA timeout setting. If you still receive a timeout exception or you anticipate that the custom methods of the service interface may be long running, you can specify an EJB transaction attribute for the stateless session bean to prevent the EJB from executing those methods in a JTA transaction.

To make a custom method exempt from timing out, you set TransactionAttributeType.NOT_SUPPORTED in the Property Inspector specifically for that method. Because a method with this transaction attribute setting will not be executed in the JTA transaction, it is your responsibility to enforce control over the transaction using the ADF Business Components methods of the oracle.jbo.ApplicationModule and oracle.jbo.Transaction interfaces. For instance, on the methods of the implementation class of the application module that you service-enabled, you will need to call am.getDBTransaction().commit() or rollback() in order to complete the transaction.

You should not change the default transaction attribute setting for the standard service methods generated for the service interface (see Table 11-1). The standard methods will execute within the default execution boundary set for the JTA transaction.

To prevent custom methods from executing in a JTA transaction:

  1. In the Application Navigator, expand the application module, expand the serviceinterface folder, then double-click the remote server class (AppModuleServiceImpl.java) file.

    In the web service generated from the StoreServiceAM application module in the StoreFrontModule application of the Fusion Order Demo, the remote server class is StoreFrontServiceImpl.java.

  2. In the source editor, locate the custom method that you want to prevent from timing out and place your cursor on the method.

  3. In the Property Inspector, expand Stateless Session Bean and choose TransactionAttributeType.NOT_SUPPORTED from the TransactionAttribute dropdown menu.

    JDeveloper updates the method by adding the annotation @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED).

    For example, for the custom service method updateCustomerInterests() it would look like this:

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void updateCustomerInterests(List<String> pCategoryIds) throws
                                                           ServiceException {
            invokeCustom((Method) _map.get("updateCustomerInterests"), 
                 new Object[] { pCategoryIds }, new String[] { null }, false);
    }
    
  4. Save the remote server class.

  5. In the Application Navigator, double-click the application module implementation class (AppModuleImpl.java) file.

    The implementation class defines the custom methods that the you exposed through the service interface. In the Fusion Order Demo, the application module implementation class is StoreServiceAMImpl.java.

  6. In the source editor, in the custom method that implements the service method that you previously set the TransactionAttribute property on, add the custom code that will commit and rollback the transaction.

    For example, if you configured the TransactionAttribute property on the service method named updateCustomerInterests(), then you would open the implementation class for the application module, locate the custom method updateCustomerInterests(), and add am.getDBTransaction().commit() and rollback() as part of the method's try and catch statements like this:

    public void updateCustomerInterests(List pCategoryIds) {
         try
         {
            if (pCategoryIds != null && pCategoryIds.size() > 0) {
                List<Integer> copyOfCategoryIds = (List<Integer>)
                                           this.cloneList(pCategoryIds);
                ViewObject selectedCategories = 
                                           this.getSelectedCategoriesShuttleList();
                RowSetIterator rsi = selectedCategories.createRowSetIterator(null);
                // remove rows for the current user not in the list of product keys
                while (rsi.hasNext()) {
                    Row r = rsi.next();
                    Number interestId = (Number)r.getAttribute("CategoryId");
                    // existing row is in the list, we're ok, so remove from list.
                    if (copyOfCategoryIds.contains(interestId)) {
                        copyOfCategoryIds.remove(interestId);
                    }
                    // if the existing row is in not list, remove it.
                    else {
                        r.remove();
                    }
                }
                rsi.closeRowSetIterator();
                // at this point, add new rows for the keys that are left
                        for (int i =0 ;i < copyOfCategoryIds.size(); i++ )  {
                            Row newRow = selectedCategories.createRow();
                            selectedCategories.insertRow(newRow);
                            newRow.setAttribute("CategoryId", (String)
                                           copyOfCategoryIds.get(i).toString());
                        }
            this.getTransaction().commit();
            }
         }
         catch (JboException e)
         {
            this.getTransaction().rollback();
            throw e;
         }
    }
    
  7. Save the application module implementation class.

11.2.20 How to Deploy Web Services to Oracle WebLogic Server

You can deploy the web service to Oracle WebLogic Server, for example to perform a second stage of testing the service. The procedure to deploy the web service will depend on whether or not you have enabled authorization for the web service. If you have enabled authorization, then preliminary steps to modify the web.xml file in the packaged application's EAR file must be performed. These steps are required only if you have enabled an authorization policy, as described in Section 11.2.14.2, "Enabling Authorization for SOAP Clients."

Caution:

Follow the procedure outlined in this section to modify the web.xml of the packaged EAR file for a web service with authorization enabled, but do not use JDeveloper to deploy the EAR file since this will overwrite the web.xml file on the target server. Instead, use a tool like the Administration Console for Oracle WebLogic Server to manually deploy the packaged application's EAR file. For details about deploying secure web service applications outside of JDeveloper, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.

Before you begin:

  1. If you created an asynchronous web service, before you can deploy the service you must configure the queues used to store the request and response. For information about configuring the request and response queues, see the Oracle Fusion Middleware Concepts Guide for Oracle Infrastructure Web Services.

  2. If you configured authorization for the web service as described in Section 11.2.14.2, "Enabling Authorization for SOAP Clients," edit the weblogic-application.xml file to define application ID parameters. This file appears in the Application Navigator in the Application Resources panel, under the Descriptors and META-INF folders.

    Add the following <application-param> definition as the first element:

    <weblogic-application xmlns="http://www.bea.com/ns/weblogic/weblogic-application"
                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      xsi:schemaLocation=
                            "http://www.bea.com/ns/weblogic/weblogic-application.xsd">
       <application-param>
          <param-name>jps.policystore.applicationid</param-name>
          <param-value>ApplicationName</param-value>
       </application-param>
       ...
    </weblogic-application>
    

    Note that the ApplicationName that you enter must match the name identified in the jazn-data.xml policy store definition:

    <jazn-data>
       <policy-store>
            <applications>
                <application>
                    <name>ApplicationName</name>
                    <app-roles>
                        ...
                    </app-roles>
                    <jazn-policy>
                        ...
                    </jazn-policy>
                </application>
            </applications>
        </policy-store>
    </jazn-data> 
    
  3. Edit the ejb-jar.xml file to add the following JpsInterceptor definition required by the EJB for application roles evaluation. This file appears in the Application Navigator under the META-INF folder of the web service project.

    <?xml version = '1.0' encoding = 'windows-1252'?>
    <ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
             http://java.sun.com/xml/ns/j2ee/ejb-jar_3_0.xsd" version="3.0" 
             xmlns="http://java.sun.com/xml/ns/javaee">
      <enterprise-beans>
        ...
      </enterprise-beans>
      <interceptors>
         <interceptor>
            <interceptor-class>
                oracle.security.jps.ee.ejb.JpsInterceptor
            </interceptor-class>
               <env-entry>
                  <env-entry-name>application.name</env-entry-name>
                  <env-entry-type>java.lang.String</env-entry-type>
                  <env-entry-value>ApplicationName</env-entry-value>
                  <injection-target>
                      <injection-target-class>
                          oracle.security.jps.ee.ejb.JpsInterceptor
                      </injection-target-class>
                      <injection-target-name>
                          application_name
                      </injection-target-name>
                  </injection-target>
               </env-entry>
         </interceptor>
         ...
      <interceptors>
      <assembly-descriptor>
         <interceptor-binding>
            <ejb-name>*</ejb-name>
            <interceptor-class>
                 oracle.security.jps.ee.ejb.JpsInterceptor
            </interceptor-class>
         </interceptor-binding>
      </assembly-descriptor>
    </ejb-jar>
    

    Note that ApplicationName must also match the application name identified in the jazn-data.xml policy store definition.

To deploy to Oracle WebLogic Server:

  1. Create an application server connection to Oracle WebLogic Server:

    1. From the main menu, choose View > Application Server Navigator.

    2. In the Application Server Navigator, right-click the Application Servers folder and choose New Application Server, and complete the Create Application Server Connection wizard.

  2. Create a service deployment profile:

    1. In the Application Navigator, right-click the project contain the web service and choose Project Properties.

    2. In the Project Properties dialog, open the Deployment page and click New.

    3. In the Create Deployment Profile dialog, choose Business Components Service Interface as the archive type, as shown in Figure 11-11.

      Figure 11-11 Dialog for Creating a Business Components Service Deployment Profile

      Create Deployment Profile dialog
  3. If you configured security for the web service using the Oracle WSM authorization policy for SOAP invocation as described in Section 11.2.14, "How to Secure the Web Service for SOAP Clients," deploy the web service to an EAR file so that you can manually edit the web.xml file.

    Note: If you did not configure security for the web service, you can skip this step and the manual editing tasks it describes. You can deploy the EAR as described in step 4.

    1. From the Application menu, choose Deploy > deployment profile for the deployment profile you created.

    2. In the Deploy wizard, on the Deployment Action page, select Deploy to EAR.

    3. Click OK.

    4. Locate the EAR file that JDeveloper creates for you. The file will appear in the deploy folder in your application's mywork folder. For example, if the application is named StoreFrontService, the EAR file is found here:

      C:\JDeveloper\mywork\StoreFrontService\deploy\StoreFrontServiceProject_bcprofile1.ear
      

      Unjar this EAR file and locate the WAR file for the service interface project. For example, the WAR file might be named StoreFrontService-MiddleTier_web.war.

    5. Unjar the WAR file and locate the web.xml file in the WEB-INF folder. Extract the web.xml file and add the following JPSWlsFilter definitions:

      <filter>
          <filter-name>JpsWlsFilter</filter-name>
          <filter-class>oracle.security.jps.ee.http.JpsFilter</filter-class>
             <init-param>
               <param-name>application.name</param-name>
               <param-value>ApplicationName</param-value>
             </init-param>
      </filter>
      <filter-mapping>
          <filter-name>JpsWlsFilter</filter-name>
          <servlet-name>
               ProjectName.server.serviceinterface.AppModuleServiceImpl
          </servlet-name>
          <dispatcher>REQUEST</dispatcher>
      </filter-mapping>
      

      When you configure the JPSWlsFilter, the application name value must match the application name set in jazn-data.xml and weblogic-application.xml files. For the filter mapping, enter the <servlet-name> that will match the servlet name already present in your web.xml. Note the filter name must match the filter name set for the JpsFilter.

    6. Repackage the modified WAR and EAR files with your edited file.

    7. Do not use JDeveloper to deploy the EAR file since this will overwrite the web.xml file on the target server. Instead, use a tool like the Administration Console for Oracle WebLogic Server to manually deploy the application EAR file. For details about deploying secure applications outside of JDeveloper, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.

  4. If you are deploying a web service EAR without configuring an Oracle WSM authorization policy for SOAP invocation, you can deploy the EAR file to Oracle WebLogic Server in JDeveloper:

    1. From the Application menu, choose Deploy > deployment profile for the deployment profile you created.

    2. In the Deploy wizard, on the Deployment Action page, select Deploy to Application Server and click Next.

    3. On the Select Server page, select the application server connection.

    4. Click OK.

11.3 Accessing Remote Data Over the Service-Enabled Application Module

ADF Business Components application modules offer built-in support for web services and for publishing rows of view object data as service data objects (SDOs). Entity objects that you create in your local data model project can utilize the SDO services that the service-enabled application module exposes on its service interface. By creating service-backed entity objects in your local project, you avoid having to work directly with the service proxy and SDOs programmatically for all common remote service data access tasks.

The Create Entity Object wizard makes it easy for you to choose between a local database and the remote ADF Business Components service when you create the entity object, as described in Section 11.3.1, "How to Use Service-Enabled Entity Objects and View Objects." In this way, service-enabled application modules provide an alternative way to access data that is not available locally in the database.

Once you create the service-backed entity object, you will be able to create view objects, view links, and view criteria to filter the data at runtime. You will also be able to utilize these view objects in your data model as though you were working with locally available data accessed from database tables.

The following sections describe how to augment your data model project using a service-enabled ADF application module.

11.3.1 How to Use Service-Enabled Entity Objects and View Objects

You will want to use the service-backed components as part of your application design strategy when one of the following conditions is true:

  • The client data model project needs to work with data from a service-enabled application that is part of a separate business process.

  • The client data model project needs to work with data from a pluggable, external service.

In the first case, you provide both sides of the service. In the second case, you may not know what the external service looks like and you may need to perform the following:

  1. Even though you might not need a Fusion implementation of the service, since the service-enabled application module's service interface is the supported unit of pluggability and the supported way of creating service-backed entity objects and view objects, you create an application module with a service interface that describes the shape you want your "canonical" pluggable service to have.

  2. After generating the service-enabled application module as described in Section 11.2.1, "How to Enable the Application Module Service Interface," you then build service-back entity objects and view objects.

  3. Finally, you can create an EJB session bean (or an SCA composite) that supports the same service interface as the "canonical" service-enabled application module that you created in Step 2 and configure the connections.xml file of the client project containing the service-enabled business components based on this service interface to use this "plugged" version instead.

For details about how to expose an application module as a web service, see Section 11.2, "Publishing Service-Enabled Application Modules."

11.3.1.1 Creating Entity Objects Backed by SDO Services

You create the service-backed entity object using the Create Entity Object wizard by specifying the URL for the WSDL document that describes the deployed service already running on an application server. The wizard uses the WSDL service description to display the list of available service view instances. In the wizard, you select among the displayed view instances to specify the entity object's data source. At the time you run the wizard, the service endpoint must be accessible in order to locate the WSDL document.

To create the entity object that uses a service view instance as its data source:

  1. In the Application Navigator, right-click the project in which you want to create the entity object and choose New.

  2. In the New Gallery, expand the Business Tier node, select ADF Business Components and then Entity Object, and click OK.

  3. On the Name page of the Create Entity Object wizard, do the following to create the entity object:

    • Enter the package name in which the entity object will be created and enter the entity object name.

    • Select Service Interface as the data source for which you want to create the entity object.

    • Enter the WSDL document URL for the published web service or click Browse to use the Find Web Services wizard to locate the remote service from the UDDI registry.

    • Select Service View Instance from the dropdown list, as shown in Figure 11-12.

      The wizard will attempt to connect with the service endpoint and populate the list from the WSDL service description. If the endpoint is unavailable, the list will remain empty.

      Figure 11-12 Service Interface as Data Source in the Create Entity Object Wizard

      Create Entity Object wizard page
  4. Click Next and modify the attributes of the entity object.

    For example, on the Attributes page, you can remove an attribute when you do not want the service-backed entity object to reference it.

  5. Click Next and modify the attributes settings of the entity object before you complete the wizard.

    For example, on the Attributes Settings page, you can enable the Refresh After Insert and Refresh After Update options for attributes that you anticipate will be modified whenever the entity is modified. Typical candidates include a version number column or an updated date column in the row.

  6. Click Finish.

11.3.1.2 Creating View Objects Backed by SDO Services

After you add the service-backed entity object to your project, you can create service-backed view objects to query and optionally filter the data from the remote service for use in the user interface. A service-backed view object is a view object whose single entity usage references an entity object that is backed an SDO service. In JDeveloper you cannot make existing view objects service-backed. Instead, when you create the view object in JDeveloper, the new view object will automatically be service-backed if its entity usage is a service-backed entity object.

Before you begin:

Create the service-backed entity object as described in Section 11.3.1.1, "Creating Entity Objects Backed by SDO Services."

To create a view object from the service-backed entity object:

  1. In the Application Navigator, right-click the service-backed entity object and choose New Default View Object.

  2. In the Create Default View Object dialog, enter the package name in which the view object will be created and enter the view object name, as shown in Figure 11-13.

    The generated view object will contain the same attributes as the entity object. You can optionally edit the view object in the overview editor to customize the query. You can also define view criteria for the view object when you want to filter the data from the remote service. For details about filtering query results, see Section 5.11, "Working with Named View Criteria."

    Figure 11-13 View Object Can Be Created from Service-Backed Entity Object

    Create Default View Object dialog

11.3.2 What Happens When You Create Service-Backed Business Components

The service-backed entity object is an entity object that encapsulates the details of accessing and, if necessary, modifying a row of data from a remote ADF Business Components service. After you use the Create Entity Object wizard to create the service-backed entity object, JDeveloper saves additional service-related metadata in the <Datasource> element of the entity component definition, as shown in Example 11-13.

The service-backed view object references the single, service-backed entity object in its metadata just as any entity-based view object does. You can use the service-backed view object just as you would use any other view object. For details about working with view objects, see Chapter 5, "Defining SQL Queries Using View Objects." The ADF runtime handles the interaction with the remote ADF Business Components service.

Example 11-13 Entity Object Metadata Shows Service View as Data Source

<Entity
   xmlns="http://xmlns.example.com/bc4j"
   Name="CustomerSEO"
   DBObjectType="table"
   AliasName="CustomerSEO"
   BindingStyle="OracleName"
   UseGlueCode="false">
   <DataSource
      DataSourceClass="oracle.jbo.datasource.svc.SIEODataSourceImpl"
      Type="ServiceInterface">
      <ServiceInterface
         ServiceName="{http://www.globalcompany.com/oesvc/}OrderEntryService"
         SDOName="{http://www.globalcompany.com/oesvc/}CustomersSVO"
         SVIName="{http://www.globalcompany.com/oesvc/}CustomersSVO"
         CreateOpName="createCustomer"
         UpdateOpName="updateCustomer"
         DeleteOpName="deleteCustomer"
         GetOpName="getCustomer"
         FindOpName="findCustomers"
         ProcessOpName="processCustomers"/>
   </DataSource>
   <Attribute
      Name="CustomerId"
      IsNotNull="true"
      Precision="6"
      Scale="0"
      ColumnName="CustomerId"
      Type="oracle.jbo.domain.Number"
      ColumnType="NUMBER"
      SQLType="NUMERIC"
      PrimaryKey="true">
   </Attribute>
   <!-- ... Other Attribute elements here ... -->
</Entity>

11.3.3 How to Update the Data Model for Service-Backed Business Components

Because the service interface exposes individual view instances, you are responsible for defining hierarchical relationships between service-backed entity objects (through associations) and service-backed view objects (through view links) in your consuming project. View links and associations are not automatically created when you create the service-backed business component. For example, if the application module of the published ADF Business Components service defines a master-detail relationship that you want to utilize, then you must define a view link for the corresponding view objects in your own project to preserve this hierarchy.

Furthermore, while you can create view links between view objects that query their data locally and service-backed view objects (and the other way around), once you define the view link, you will not be able to create entity-based view objects with the following entity object usages:

  • The view object will not be able to reference a secondary entity usage that is a service-backed entity object.

  • The view object will not be able to reference a primary entity usage that is a service-backed entity object with secondary entity usages.

The same restrictions apply to associations in the client project between regular entity objects and service-backed entity objects: while you can create the associations, you will not be able to create view objects.

You use the Create View Link wizard to specify relationships between the view objects that your project defines, as shown in Figure 11-14. For details about creating view links, see Section 5.6.2, "How to Create a Master-Detail Hierarchy for Entity-Based View Objects."

Figure 11-14 One to Many Relationship Defined in Create View Link Wizard

Create View Link wizard page

View links you create may define relationships between service-backed view objects and view objects that query locally accessed database tables. For example, you might choose to drive a database-derived detail view object with a service-backed master view object. You can create view links with the combinations shown in Table 11-2.

Table 11-2 Supported View Link Combinations Involving Service-Backed View Objects

Use Case Master View Object Type View Linked Detail View Object Type View Link Cardinality

Local master rows with remote details

Query-based

Service-backed

One-to-many

Remote master rows with local details

Service-backed

Query-based

One-to-many

Local master rows with remote reference information

Query-based

Service-backed

Many-to-one

Remote master rows with local reference information

Service-backed

Query-based

Many-to-one


Once you have defined the desired view hierarchy, using the Create View Link wizard, you use the overview editor for your project's application module to define new view instances on the data model, as shown in Figure 11-15. The updated data model allows you to expose the view objects as ADF data controls that enable databinding with the user interface components of the Fusion web application. For details about updating the data model, see Section 9.2.3.2, "Adding Master-Detail View Object Instances to an Application Module."

Figure 11-15 Data Model Contains Service View Instances

Data Model overview editor page

11.3.4 How to Configure the Service-Backed Business Components Runtime

Before you can run your application and interact with the published service-enabled ADF application module to invoke service operations, you need to describe the published service, including the service's endpoint provider type and other configuration information. The ADF Business Components ServiceFactory class (oracle.jbo.client.svc.ServiceFactory) returns a proxy for the service, then uses the service proxy to invoke the service operations. The service factory can return proxies for three different service endpoint providers, to support these transport protocols:

  • When the service endpoint provider is ADF Business Component, the transport protocol is EJB RMI.

  • When the service endpoint provider is SOA Fabric, the transport protocol is SOA Fabric SDO binding.

  • When the service endpoint provider is SOAP (for JAX-WS clients), the transport protocol is SOAP.

To configure the consuming application to invoke published service operations:

  1. Add the bcProfileName_Common.jar file for the SDO's generated classes to the client project's classpath.

  2. Update the connections.xml file in the client project's .adf/META-INF folder to describe the published ADF Business Components service.

    The updates you make to the file will depend on the transport protocol your application uses: EJB RMI protocol, SOA Fabric SDO binding, or SOAP protocol (for JAX-WS clients).

11.3.4.1 Adding the SDO Client Library to the Classpath

Before your application can access the published service, the service consuming project must have access to the generated SDO classes and their schema definitions. These files are packaged in the bcProfileName_Common.jar file generated by the development team responsible for publishing the service.

To make the SDO classes available to your application, obtain the bcProfileName_Common.jar file from the service-provider team and place this JAR file in a folder of your local project. For example, you may copy the JAR file into your project's deploy folder. You can then use JDeveloper to add the JAR file to your project's classpath with a SDO client library you create. For steps to generate the SDO classes JAR file, see Section 11.2.20, "How to Deploy Web Services to Oracle WebLogic Server."

To add the SDO client library to the classpath:

  1. In the Application Navigator, right-click your project folder and choose Project Properties.

  2. In the Project Properties dialog, select Libraries and Classpath and click Add Libraries.

  3. In the Add Library dialog, click New to create the SDO client library.

  4. In the Create Library dialog, click Add Entry to add a classpath entry.

  5. In the Select Path Entry dialog, browse to the folder that contains the bcProfileName_Common.jar file and select the file to view it in the Create Library dialog.

    The Select Path Entry dialog lets you browse the file system or local area network to locate the JAR file. If you cannot browse the deploy folder of the service-provider's application workspace to obtain the JAR file, you must obtain the file and copy it into your own project's folder. For example, you may have copied the JAR file into your project's deploy folder.

  6. Click OK in the dialogs to display the Project Properties dialog with the SDO client library selected. Click OK to add the library to the classpath.

    Figure 11-16 shows the SDO client library with the name ServiceProvider_Common.jar selected. In this case, the library name is the same as the JAR file name. Optionally, you can edit the library name in the Create Library dialog.

    Figure 11-16 SDO Client Library Classpath Entry

    SDO Client Library Classpath Entry

11.3.4.2 Registering the ADF Business Components Service in the Consuming Application's connections.xml for the EJB RMI Protocol

When the service endpoint provider is ADF Business Components, the service factory will return an EJB object proxy bound to a stateless session bean running in the EJB container. You must provide the JNDI context information to allow the consuming application to look up the published service.

Lookup information that you provide to register the published ADF Business Components service appears in the consuming Fusion web application's connections.xml file, located in the .adf/META-INF folder relative to the application. The ADF connection architecture uses this file to encapsulate the details of the service endpoint provider.

The JNDI lookup information you provide will depend on whether the published service runs locally (in the same JVM) with the consuming application or runs remotely on a separate server from the consuming application. Typically, the ADF Business Components service is in a different application from the consuming application and is therefore run remotely.

To register the published service with your client application, update the connections.xml file following the example in Example 11-14. When the ADF Business Components service runs local to the consuming application (as occurs when you run within JDeveloper), the service factory needs only the JNDI name to look up the service.

Note:

When you deploy the calling application to standalone Oracle WebLogic Server, you will use Oracle Enterprise Manager to configure the JNDI context properties instead of editing the connections.xml file. For instructions, refer to the online documentation in Oracle Enterprise Manager.

Example 11-14 Client connections.xml File Registers the Local EJB ADF Business Components Service

<References xmlns="http://xmlns.oracle.com/adf/jndi">
  <Reference name="{www.globalcompany.com}StoreFrontService" 
             className="oracle.jbo.client.svc.Service" xmlns="">
     <Factory className="oracle.jbo.client.svc.ServiceFactory"/>
     <RefAddresses>
       <StringRefAddr addrType="serviceInterfaceName">
        <Contents>oracle.foddemo.storefront.store.service.common.
                                                serviceinterface.StoreFrontService</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="serviceEndpointProvider">
          <Contents>ADFBC</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="jndiName">
          <Contents>StoreFrontServiceBean#oracle.fodemo.storefront.store.service.common.
                                                 serviceinterface.StoreFrontService</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="serviceSchemaName">
          <Contents>StoreFrontAMService.xsd</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="serviceSchemaLocation">
          <Contents>oracle/fodemo/storefront/store/service/common/serviceinterface/</Contents>
       </StringRefAddr>
     </RefAddresses>
  </Reference>
  ...
</References>

When the ADF Business Components service runs remotely to the calling client, then remote JNDI context information needs to be added to the connections.xml file. You can edit these JNDI context properties in the connections.xml file, as shown in Example 11-15:

  • jndiFactoryInitial should be set to weblogic.jndi.WLInitialContextFactory.

  • jndiProviderURL is the JNDI provider URL that indicates the location of the JNDI server. The URL should be composed as t3://<hostname>:<server port>.

    For example, specify a URL like: t3://localhost:8888, where t3 is the Oracle WebLogic protocol, localhost is the host name that the remote Oracle WebLogic Server instance runs in, 8888 is the port number.

  • jndiSecurityPrincipal specifies the principal (user name) with permission to access the remote JNDI.

    When you deploy the service to standalone Oracle WebLogic Server, the user name can be read from the file.

  • jndiSecurityCredentials specifies the credentials (password) to be used for the security principal.

    As Example 11-11 shows, when you deploy the service to standalone Oracle WebLogic Server in a test environment, you can specify credentials in plain text for the JNDI provider. For example, you can specify weblogic/weblogic1 which are the default administrator user name/password credentials with sufficient privileges to access JNDI provider for Oracle WebLogic Server.

    When you deploy the service to a production environment, you must remove the plain text password to avoid creating a security vulnerability. As Example 11-15 shows, the connections.xml file must contain <SecureRefAddr addrType="jndiSecurityCredentials"/> with no password. To configure the service password for standalone Oracle WebLogic Server, you must use Oracle Enterprise Manager, which will store the encrypted password in Oracle's credential store.

Example 11-15 Client connections.xml File Registers the Remote EJB ADF Business Components Service

<References xmlns="http://xmlns.oracle.com/adf/jndi">
  <Reference name="{www.globalcompany.com}StoreFrontService" 
             className="oracle.jbo.client.svc.Service" xmlns="">
     <Factory className="oracle.jbo.client.svc.ServiceFactory"/>
     <RefAddresses>
       <StringRefAddr addrType="serviceInterfaceName">
        <Contents>oracle.foddemo.storefront.store.service.common.
                                                serviceinterface.StoreFrontService</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="serviceEndpointProvider">
          <Contents>ADFBC</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="jndiName">
          <Contents>StoreFrontServiceBean#oracle.fodemo.storefront.store.service.common.
                                                 serviceinterface.StoreFrontService</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="jndiFactoryInitial">
          <Contents>weblogic.jndi.WLInitialContextFactory</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="jndiProviderURL">
          <Contents>t3://localhost:8888</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="jndiSecurityPrincipal">
          <Contents>a_username</Contents>
       </StringRefAddr>
       <SecureRefAddr addrType="jndiSecurityCredentials"/>
       <StringRefAddr addrType="serviceSchemaName">
          <Contents>StoreFrontAMService.xsd</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="serviceSchemaLocation">
          <Contents>oracle/fodemo/storefront/store/service/common/serviceinterface/</Contents>
       </StringRefAddr>
     </RefAddresses>
  </Reference>
  ...
</References>

11.3.4.3 Registering the ADF Business Components Service in the Consuming Application's connections.xml for the SOAP Protocol

When the service endpoint provider is SOAP, the service factory will create a dynamic JAX-WS client proxy. You must provide the WSDL URL and port name to allow the consuming application to look up the published service. Additionally, for the SOAP client, Oracle Web Service Manager (Oracle WSM) client security policy can be attached as part of the SOAP header.

Lookup information that you provide to register the published ADF Business Components service appears in the consuming Fusion web application's connections.xml file, located in the .adf/META-INF folder relative to the application. The ADF connection architecture uses this file to encapsulate the details of the service endpoint provider.

Note:

When you deploy the calling application to standalone Oracle WebLogic Server, you will use Oracle Enterprise Manager to configure the JNDI context properties instead of editing the connections.xml file. For instructions, refer to the online documentation in Oracle Enterprise Manager.

To register the published service with your client application for the SOAP protocol, depending on whether your application uses identity propagation or identity switching, update the connections.xml file following the example in either Example 11-16 or Example 11-17. Identity propagation and switching are similar in that each process involves propagating an identity. In Fusion web applications, identity propagation involves propagating the identity that is currently executing code. Identity switching, on the other hand, involves propagating an application identity that is different from that currently executing code.

To register the published service with your client application so the the user identity will be switched based on the credential key, specify the clientside policy oracle/wss11_username_token_with_message_protection_client_policy in the connections.xml file following the example in Example 11-16.

Note:

The connections.xml file supports Oracle WSM security policy client overrides. When the security policy is oracle/wss11_username_token_with_message_protection_client_policy, the csf-key property can be overridden to specify the consuming application's credentials.

Example 11-16 Client connections.xml File Registers the Remote Business Components Service for the SOAP Protocol Using Identify Switching

<Reference name="{http://xmlns.oracle.com/apps/sample/hrService/}HrService"
className="oracle.jbo.client.svc.Service" xmlns="">
   <Factory className="oracle.jbo.client.svc.ServiceFactory"/>
   <RefAddresses>
      <StringRefAddr addrType="serviceInterfaceName">
            <Contents>oracle.apps.sample.hrService.HrService</Contents>
      </StringRefAddr>
      <StringRefAddr addrType="serviceEndpointProvider">
         <Contents>SOAP</Contents>
      </StringRefAddr>
      <StringRefAddr addrType="webServiceConnectionName">
         <Contents>HrServiceConnection</Contents>
      </StringRefAddr>
      <StringRefAddr addrType="serviceSchemaName">
         <Contents>HrService.xsd</Contents>
      </StringRefAddr>
      <StringRefAddr addrType="serviceSchemaLocation">
         <Contents>oracle/apps/sample/hrService/</Contents>
      </StringRefAddr>
   </RefAddresses>
</Reference>

<Reference name="HrServiceConnection"
         className="oracle.adf.model.connection.webservice.impl.WebServiceConnectionImpl" xmlns="">
   <Factory
         className="oracle.adf.model.connection.webservice.api.WebServiceConnectionFactory"/>
   <RefAddresses>
      <XmlRefAddr addrType="WebServiceConnection">
         <Contents>
            <wsconnection
               description="http://rws65094fwks:7202/MySampleSvc/HrService?WSDL"
               service="{http://xmlns.oracle.com/apps/sample/hrService/}HrService">
               <model
                  name="{http://xmlns.oracle.com/apps/sample/hrService/}HrService"
                  xmlns="http://oracle.com/ws/model">
                  <service name="{http://xmlns.oracle.com/apps/sample/hrService/}HrService">
                     <port name="HrServiceSoapHttpPort"
                        binding="{http://xmlns.oracle.com/apps/sample/hrService/}HrServiceSoapHttp"
                        portType="http://xmlns.oracle.com/apps/sample/hrService/}HrService">
                        <call-properties xmlns="http://oracle.com/adf">
                           <call-property id="csf-key" xmlns="">
                               <name>csf-key</name>
                               <value>meuser.credentials</value>
                            </call-property>
                        </call-properties>
                        <policy-references xmlns="http://oracle.com/adf">
                           <policy-reference category="security"
                            uri="oracle/wss11_username_token_with_message_protection_client_policy"
                            enabled="true"
                            id="oracle/wss11_username_token_with_message_protection_client_policy"
                            xmlns=""/>
                        </policy-references>
                        <soapaddressUrl="http://rws65094fwks:7202/MySampleSvc/HrService"
                            xmlns="http://schemas.xmlsoap.org/wsdl/soap/"/>
                     </port>
                  </service>
               </model>
            </wsconnection>
         </Contents>
      </XmlRefAddr>
   </RefAddresses>
</Reference>

To register the published service with your client application so the the user identity will be propagated to the caller, specify the clientside policy oracle/wss11_saml_token_with_message_protection_client_policy in the connections.xml file following the example in Example 11-17.

Example 11-17 Client connections.xml File Registers the Remote Business Components Service for the SOAP Protocol Using Identify Propagation

<Reference name="{http://xmlns.oracle.com/apps/sample/hrService/}HrService"
className="oracle.jbo.client.svc.Service" xmlns="">
   <Factory className="oracle.jbo.client.svc.ServiceFactory"/>
   <RefAddresses>
      <StringRefAddr addrType="serviceInterfaceName">
            <Contents>oracle.apps.sample.hrService.HrService</Contents>
      </StringRefAddr>
      <StringRefAddr addrType="serviceEndpointProvider">
         <Contents>SOAP</Contents>
      </StringRefAddr>
      <StringRefAddr addrType="webServiceConnectionName">
         <Contents>HrServiceConnection</Contents>
      </StringRefAddr>
      <StringRefAddr addrType="serviceSchemaName">
         <Contents>HrService.xsd</Contents>
      </StringRefAddr>
      <StringRefAddr addrType="serviceSchemaLocation">
         <Contents>oracle/apps/sample/hrService/</Contents>
      </StringRefAddr>
   </RefAddresses>
</Reference>

<Reference name="HrServiceConnection"
         className="oracle.adf.model.connection.webservice.impl.WebServiceConnectionImpl" xmlns="">
   <Factory
         className="oracle.adf.model.connection.webservice.api.WebServiceConnectionFactory"/>
   <RefAddresses>
      <XmlRefAddr addrType="WebServiceConnection">
         <Contents>
            <wsconnection
               description="http://rws65094fwks:7202/MySampleSvc/HrService?WSDL"
               service="{http://xmlns.oracle.com/apps/sample/hrService/}HrService">
               <model
                  name="{http://xmlns.oracle.com/apps/sample/hrService/}HrService"
                  xmlns="http://oracle.com/ws/model">
                  <service
                     name="{http://xmlns.oracle.com/apps/sample/hrService/}HrService">
                     <port name="HrServiceSoapHttpPort"
                        binding="{http://xmlns.oracle.com/apps/sample/hrService/}HrServiceSoapHttp"
                        portType="http://xmlns.oracle.com/apps/sample/hrService/}HrService">
                        <policy-references xmlns="http://oracle.com/adf">
                           <policy-reference category="security"
                                uri="oracle/wss11_saml_token_with_message_protection_client_policy"
                                enabled="true"
                                id="oracle/wss11_saml_token_with_message_protection_client_policy"
                                xmlns=""/>
                        </policy-references>
                        <soap addressUrl="http://rws65094fwks:7202/MySampleSvc/HrService"
                              xmlns="http://schemas.xmlsoap.org/wsdl/soap/"/>
                     </port>
                  </service>
               </model>
            </wsconnection>
         </Contents>
      </XmlRefAddr>
   </RefAddresses>
</Reference>

11.3.4.4 Registering the ADF Business Components Service in the Consuming Application's connections.xml for Fabric SDO Binding

When the service endpoint provider is SOA Fabric, the service factory will return a SOA Fabric composite proxy and call the service running inside a Fabric composite through Fabric's SDO binding. You must provide the name of the Fabric composite to allow the consuming application to look up the published service.

Lookup information that you provide to register the published ADF Business Components service appears in the consuming Fusion web application's connections.xml file, located in the .adf/META-INF folder relative to the application. The ADF connection architecture uses this file to encapsulate the details of the service endpoint provider.

Note:

When you deploy the calling application to standalone Oracle WebLogic Server, you will use Oracle Enterprise Manager to configure the JNDI context properties instead of editing the connections.xml file. For instructions, refer to the online documentation in Oracle Enterprise Manager.

To register the published service with your client application for the Fabric protocol, update the connections.xml file following the example in Example 11-18, where fabricAddress is the name of the Fabric composite for the published service.

Example 11-18 Client connections.xml File Registers the Remote Business Components Service for the SOA Fabric Protocol

<References xmlns="http://xmlns.oracle.com/adf/jndi">
  <Reference name="{www.globalcompany.com}StoreFrontService" 
             className="oracle.jbo.client.svc.Service" xmlns="">
     <Factory className="oracle.jbo.client.svc.ServiceFactory"/>
     <RefAddresses>
       <StringRefAddr addrType="serviceInterfaceName">
        <Contents>oracle.foddemo.storefront.store.service.common.
                                             serviceinterface.StoreFrontService</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="serviceEndpointProvider">
          <Contents>Fabric</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="fabricAddress">
         <Contents>fabric_StoreFrontService</Contents>
       <StringRefAddr addrType="serviceSchemaName">
          <Contents>StoreFrontAMService.xsd</Contents>
       </StringRefAddr>
       <StringRefAddr addrType="serviceSchemaLocation">
          <Contents>oracle/fodemo/storefront/store/service/common/serviceinterface/</Contents>
       </StringRefAddr>
     </RefAddresses>
  </Reference>
  ...
</References>

11.3.5 How to Test the Service-Backed Components in the Business Component Browser

Before you can launch the Business Component Browser, your project must meet the runtime requirements as described in Section 11.3.4, "How to Configure the Service-Backed Business Components Runtime." The Business Component Browser will display the view objects you create from the remote service and allow you to interact with the service to perform standard CRUD operations.

Because the application module that you run can access locally queried data and remotely queried data together, service-backed view objects and database-derived view objects will display in the same Browser. If the endpoint is unavailable at the time you select the service-backed view object in the Business Component Browser, you will get a runtime exception.

For details about running the Business Component Browser, see Section 6.3.1, "How to Run the Business Component Browser."

11.3.6 How to Invoke Operations of the Service-Backed Components in the Consuming Application

The ADF Business Components service interface requires that you return a service proxy to ensure that operations you invoke use the transport protocol specified by the published service.

Before you begin:

You need to ensure that the consuming application has the correct libraries on the classpath. In the Application Navigator, double-click the project and in the Project Properties dialog, select Libraries and Classpath and confirm the following libraries appear:

  • Java EE 1.5

  • Oracle XML Parser v2

  • BC4J Service Client

  • JAX-WS Client

  • The service's common JAR file

As Example 11-19 shows, when you invoke the operation, you perform the following tasks:

  1. Import the oracle.jbo.client.svc.ServiceFactory class and published service class.

  2. Call getServiceProxy() on the service factory object and pass in the service name in the form <serviceName>.NAME. The ADF service factory embeds a SDOHelperContext ID in the service proxy object returned by this method to ensure delivery of the latest ADF Business Component service schema metadata to the SDO.

    The schema (.xsd files) for the service object may be stored in MDS and may have been extended for example to add more business component attributes, extend existing types, or define new types. The local helper context allows customization of individual service's schema definitions without affecting other service's SDO metadata or requiring restarting the application.

  3. Call create() on a data factory object, where the proxy object is obtained from the getServiceProxy() call.

  4. Invoke the operation on the proxy object and return a data object.

  5. Save the data object return as XML.

Example 11-19 Obtaining and Invoking a Service Proxy in the Consuming Application

import commonj.sdo.DataObject;
import commonj.sdo.helper.DataFactory;
import commonj.sdo.helper.XMLHelper;
import hr.common.Dept;
import hr.common.serviceinterface.HRAppService;
import oracle.jbo.client.svc.ServiceFactory;
   ...
   {
      HRAppService proxy = (HRAppService) ServiceFactory.getServiceProxy(HRAppService.NAME);

      Dept dept = (Dept)
               ServiceFactory.getDataFactory(proxy).create("http://example.com/hr/common/" "Dept");
      dept.setDname("ENGINEERING");
      ...
      dept = proxy.createDept(dept);
      String xml = ServiceFactory.getXMLHelper(proxy).save((DataObject) dept,
                                   "http://example.com/hr/common/", "dept");
      out.print(xml);
   }

11.3.7 What Happens at Runtime: When the Application Accesses the Published Application Module

The ADF runtime obtains the data source information from the service-backed entity object XML definition to automate interactions with the service interface methods as needed. By using the service-backed entity object, you avoid having to work directly with the service proxy and service data objects programmatically for all common remote service data access tasks. The ADF service factory looks up the service and then uses the service interface you specified in the connections.xml to invoke the service methods.

When your application accesses a remote ADF Business Components service, each remote call is stateless, and the remote service will not participate in the same transaction as the business component that uses a service-enabled application module's service interface.

In the majority of the cases, calls to remote services will be informational in nature and will not make changes to remote objects. However, if you must use a remote service to make changes, then keep these points in mind:

  • An exception thrown by the remote service will cause the local transaction to fail.

  • If you successfully call a remote service that results in modifying data, and then subsequently your local transaction fails for any reason, then it is the responsibility of your error handling code to perform a compensating transaction against the remote service to "undo" the previous change made.

11.3.8 What You May Need to Know About Service-Backed Entity Objects and View Objects

You will use some web services to access reference information. However, other services you call may modify data. This data modification might be in your own company's database if the service was written by a member of your own or another team in your company. If the web service is outside your firewall, of course the database being modified will be managed by another company. In either of these situations, it is important to understand that any data modifications performed by a web service you invoke will occur in its own distinct transaction unrelated to the service-enabled application module's current unit of work. For example, if you have invoked a web service that modifies data and then you later call rollback() to cancel the pending changes in the application module's current unit of work, rolling back the changes has no effect on the changes performed by the web service you called in the process. You may need to invoke a corresponding web service method to perform a compensating change to account for your rollback of the application module's transaction.

At runtime, ADF handles the interaction with the remote ADF Business Components service. However, you should be aware that service-backed business components have the following design time restrictions that may restrict your application's runtime behavior. For more details about how these restrictions apply at design time, see Section 11.3.3, "How to Update the Data Model for Service-Backed Business Components."

  • View objects that you create cannot reference a service-backed entity object as a secondary entity object usage.

  • View objects that you create cannot produce a flattened join from two or more related entity objects when at least one of those entity objects is a service-backed entity object.

  • Service-backed view objects that you create from service-backed entity objects will not reference secondary entity usages.

For more details about how these restrictions apply at design time, see Section 11.3.3, "How to Update the Data Model for Service-Backed Business Components."