Oracle® Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework 11g Release 2 (11.1.2.1.0) Part Number E16182-02 |
|
|
PDF · Mobi · ePub |
This chapter describes how to publish ADF application modules to make them available as external services in a Fusion web application, and how to incorporate the published application module as an external service in the Fusion web application.
This chapter includes the following sections:
Section 11.2, "Publishing Service-Enabled Application Modules"
Section 11.3, "Accessing Remote Data Over the Service-Enabled Application Module"
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.
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.
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.
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.
ADF Business Components 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.
Any development team can publish a service-enabled application module to contribute to the 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 the web applications may 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 web 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 web service is configured to participate in the same transaction.
You may find it helpful to understand other ADF features before you start working with ADF Business Components services. Following are links to other functionality that may be of interest.
For information about the SCA and service data object (SDO) standards, see the Open SOA web site at http://www.osoa.org
.
For further background about web services and Oracle WebLogic Server support for web services, see Oracle Fusion Middleware Introducing Web Services.
For details about how to delegate data operations to the SDO data provider through the use of the Business Process Execution Language (BPEL) entity variable, see the Oracle Fusion Middleware Developer's Guide for Oracle SOA Suite.
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."
For API documentation related to the oracle.jbo
package, see the following Javadoc reference document:
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 the SDO 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 SDO components based on view instance that your application module defines 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.
Note:
JDeveloper only supports generating SDO components for view objects of a service-enabled application module. Currently, no other Oracle ADF business components may be defined as SDO components.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.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 |
---|---|---|
|
|
Creates a single ADF Business Components view row. |
|
|
Updates a single ADF Business Components view row. |
|
|
Deletes a single ADF Business Components view row. |
|
|
Updates a ADF Business Components view row if one exists; otherwise, creates a new one. |
|
|
Gets a single ADF Business Components view row by primary key. |
|
|
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." |
|
|
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. |
|
|
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. |
|
|
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 |
Note:
When you generate a SDO class for a parent view object, JDeveloper automatically generates SDO classes for view instances that extend the parent in a polymorphic collection. For details about polymorphic view objects, see Section 42.6.5, "Working with Polymorphic View Rows."For information on how to create SDO classes for child view objects, see Section 11.2.4, "How to Service-Enable Individual View Objects."
It may be helpful to have an understanding of how the SDO framework supports service-enabled ADF application modules 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."
When you create the service-enabled application module, do not create it in a project that already contains a standard web service (a Java class or interface with the @WebService
annotation). JDeveloper deployment profiles do not support deploying a standard web service and an ADF Business Service web service from the same project. If you attempt to deploy the ADF Business Service web service from the same project as a standard web service, the deployment will fail with an Oracle WebLogic Server exception error.
Complete these tasks:
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."
Create the desired application module as described in Section 9.2.1, "How to Create an Application Module."
Optionally, set JDeveloper preferences to specify a default suffix for the names of generated SDO classes, modify the default subpackage where the service common interface and classes reside, and set the default namespace prefix for the generated SDO schema and web service as described in Section 11.2.13, "How to Set Preferences for Generating the ADF Web Service Interface."
If you want to expose custom find operations on the service, create declarative view criteria to specify the custom query as described in Section 5.11.1, "How to Create Named View Criteria Declaratively."
To create the web service interface:
In the Application Navigator, double-click the application module.
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.
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.
To generate a method that will return the static control hints (UI hints) defined on the view instances that you service 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.
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.
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 service-interface supported data types, such as a Java primitive type, or a list of the service-interface supported data types (including oracle.jbo.server.ViewRowImpl
, java.util.List<
ViewRowImpl
>
, oracle.jbo.AttributeList
, java.util.List<
AttributeList
>
, or java.util.List<
PrimitiveType
>
).
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 ADF Web 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:
In the Selected list, expand return or parameters and select the item.
Enter the Java element data type in Element Java Type.
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.
To expose service information messages such as warnings and exceptions for a custom method or warnings for process operation methods, select Include Warnings in Return Service Data Object. For example, you might want display an informational message when a method returns the total employee compensation and the total is outside of the desired range.
If Include Warnings is not selected, no informational messages will be returned with the service response.
This option is only enabled when the method does not return a view row or a list of view rows. When the method returns view rows, the underlying view object determines whether the method supports warnings, as described Section 11.2.4, "How to Service-Enable Individual View Objects."
The informational messages (and warnings) are reported as part of the return object. JDeveloper generates appropriate wrappers as the return objects, and the wrappers contain the actual method return and the informational messages.
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 enable the available data manipulation operations supported on the exposed methods, as shown in Figure 11-1.
In the Basic Operations tab, select the data manipulation operations for the currently selected view instance and in the Method Name field, change the names of the selected service operations to the names that you prefer to expose in the service interface.
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."
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 the service interface generated, the corresponding method will not execute at runtime. Therefore, after changing the underlying view criteria, you must regenerate the service interface.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.
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.
Click Next to review the custom methods that your service view instances will expose.
Click Finish.
JDeveloper generates the service interface class and enables any view instance options you have chosen, as shown in Figure 11-3.
Do not modify the generated files for the service-enabled application module. The generated files implement required methods of the service interface. An exception to this are use cases that require adding Java annotations to the remote service implementation class. For example, annotations that you add in the remote common interface implementation class let you attach security policies, as described in Section 11.2.14, "How to Secure the ADF Web Service for Access By SOAP Clients."
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
In addition, the connections.xml
file is created when you first create an ADF Business Components service. Although this file is is only used by the web service client (the consuming application), it is generated with the service-enabled application module as a convenience. This file appears in the Application Navigator in the Application Resources panel, under the Descriptors and ADF META-INF nodes.
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 interface 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.serviceinterface; ... 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; ... }
The remote service schema file is an XML schema file which represents the web service schema, as shown in Figure 11-5.
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.
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); } ... }
The connections.xml
file is used by a web service client to look up the service. The ADF Business Components service factory provides 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 nodes.
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>
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 (for example, int
, Integer
, and Long
)
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, including Java primitive type
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:
Looks up the row in the corresponding view object instance by primary key and/or alternate key
If the row is not found, then creates a new row
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.
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.
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:
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."
Optionally, set JDeveloper preferences to specify a default suffix for the names of generated SDO classes and set the default namespace prefix for the generated SDO schema and web service as described in Section 11.2.13, "How to Set Preferences for Generating the ADF Web Service Interface."
To set the SDO name and namespace for a view object:
In the Application Navigator, double-click the view object.
In the overview editor, click the Java navigation tab and click the Edit java options button.
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 component that you can assign to group similar SDO components together by entering the same URI.
A default SDO namespace is created for you based on the SDO component'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.
Optionally, select Support Warnings when you want to be able to extract warnings associated with the view rows of the service interface object. For example, your view object might have a range validator defined on the Salary
attribute and failure handling for the validator is specified as Informational Warning.
If Support Warnings is not selected, no informational messages will be returned with the service response.
When enabled and a warning is generated from the underlying ADF business component object for one of the standard service operations or custom operations, the warning information will be captured by the response object. You can use the methods generated for the service object result class to extract the messages from the view rows, as described in Section 11.2.7.4, "Service Data Object Result Class and Interface."
Click OK.
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.
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 then use the Details tab in the overview editor for the view object to hide the selected attribute from the SDO component.
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:
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."
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:
In the Application Navigator, double-click the view object.
In the overview editor, click the Attributes navigation tab.
In the Attributes page of the overview editor, select the attribute corresponding to the property that you want to exclude and then click the Details tab and deselect SDO Property.
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 9.12.1.3, "Calling a Web Service Method Using the Proxy Class in an Application Module," 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.
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:
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."
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:
In the Application Navigator, double-click the view object.
In the overview editor, click the Attributes navigation tab.
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.
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.
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.
Click OK.
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 may not automatically be executed on the detail view object. Post operations on the detail view object are supported by default when the primary entity object of the master view object is composed with the primary entity object of the detail view object. This master-detail relationship is known as a composition association and is the default type associate created in JDeveloper, as described in Section 4.3.6, "What You May Need to Know About Composition Associations."
To support create/merge/update/process methods that post child details along with the parent, you you have created a view link to define the master-detail relationship according to one of these scenarios:
The view link uses the default composition association, then post operations on the detail view object are supported by default.
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.
The custom property provides an alternative to using a composition association 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).
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.
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 may also find it helpful to have an understanding of how master-detail relationships are defined using view links or entity associations:
For more information about view links, see Section 5.6, "Working with Multiple Tables in a Master-Detail Hierarchy."
For more information about associations, see Section 4.3, "Creating and Configuring Associations."
Complete these tasks:
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."
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.
If the view link is based on an association, then the destination accessor must exist for the association's destination entity object. To generate one, use the Relationship page of the overview editor for the association.
To support nested processing in a master-detail hierarchy:
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.
In the overview editor, click the General navigation tab.
The overview editor for the view link and the association display similar selections.
In the General page, expand the Custom Properties section, and then click the Add Custom Property icon and enter SERVICE_PROCESS_CHILDREN
for the property and enter true
for the property value, as shown in Figure 11-8.
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
Do not modify the files generated for service-enabled view objects. The generated files implement required methods of the view object SDO interface.
The view object SDO interface contains strongly typed accessors for the SDO properties, as shown in Example 11-4.
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.
The view object SDO schema file, as shown in Figure 11-13, is an XML Schema file which represents the SDO schema.
The view object SDO result class is a container object that allows a service operation to return a list of view rows (wrapped in service data objects) and a list of warnings associated with these view rows. Specifically, the service get operation returns the original object, while the create/update/merge/find/process operations return a wrapper object that contains a list of the original object and a list of information messages, and the delete operation returns only the informational message. If you have enabled the Support Warnings option for the service-enabled view object, you can use the generated method result interface to extract warnings.
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); } }
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.
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 may also find it helpful to have an understanding of how to filter view object queries using bind variables. For more information, see Section 5.10, "Working with Bind Variables."
Complete these tasks:
Create the desired application module as described in Section 9.2.1, "How to Create an Application Module."
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:
In the Application Navigator, double-click the application module.
In the overview editor, click the Service Interface navigation tab and click the Edit attributes of Service Interface icon.
Alternatively, you can select Edit Service Custom Methods if you have already defined the service interface.
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.
To expose the find operation, select the view instance, click the View Criteria Find Operations tab, and then click the Add View Criteria button.
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.
You can double-click the XML name to customize the bind variable name shown in the XML definition for the service.
Click OK.
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 AppModuleName
Impl.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.
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; } }
It may be helpful to have an understanding of how the SDO framework supports service-enabled 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 may also find it helpful to have an understanding of how to filter view object queries using bind variables. For more information, see Section 5.10, "Working with Bind Variables."
Complete these tasks:
Create the custom application module class as described in Section 9.7.1, "How to Generate a Custom Class for an Application Module."
Create the custom find method to programmatically filter a query result and set the required bind variable as described in Section 5.10.5, "How to Add a WHERE Clause with Named Bind Variables at Runtime."
To expose a find method that sets a required bind variable:
In the Application Navigator, double-click the application module.
In the overview editor, click the Service Interface navigation tab and click the Edit attributes of Service Interface icon.
Alternatively, you can click the Edit Service Custom Methods icon if you have already defined the service interface.
In the Edit Service Interface dialog, select Service View Instances from the navigation list and add the find method that you defined to the Selected list.
Click OK.
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.
It may be helpful to have an understanding of how the SDO framework supports service-enabled 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 may also find it helpful to have an understanding of invoking web services using asynchronous request-response. For more information, see Oracle Fusion Middleware Concepts Guide for Oracle Infrastructure Web Services.
Complete this task:
To expose asynchronous web service methods:
In the Application Navigator, double-click the application module.
In the overview editor, click the Service Interface navigation tab and click the Edit attributes of Service Interface icon.
In the Edit Service Interface dialog, select Generate Asynchronous Web Service Methods.
Click OK.
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); } }
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:
The client calls for the asynchronous operation. (In the figure, Step 1.)
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)
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.
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.
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:
From the main menu, choose Tools > Preferences.
In the Preferences dialog, expand ADF Business Components and choose Class Naming.
In the View Object suffix list, enter a suffix for SDO, for example, SDO
.
To set the default subpackage for the generated service interface:
From the main menu, choose Tools > Preferences.
In the Preferences dialog, expand ADF Business Components and choose Packages.
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:
From the main menu, choose Tools > Preferences.
In the Preferences dialog, expand ADF Business Components and choose View Objects.
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/
.
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.
To secure the web service for SOAP clients:
Configure an Oracle WSM authentication policy.
Configure an Oracle WSM authorization policy.
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 annotation.
You can enable permission checking to enable only users with sufficient privileges to invoke a service method on the service interface. Permission checking is configured on the remote server class using this Oracle WSM authorization annotation:
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 the authorization policies, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.
ADF service interface framework also provides an EJB interceptor ServicePermissionCheckInterceptor
which does the same permission check as oracle/binding_permission_authorization_policy
, and additionally covers RMI invocation to services. If your services will always be invoked through SOAP, you should attach the Oracle WSM oracle/binding_permission_authorization_policy
authorization policy. If your services will also be invoked through RMI, you should attach the EJB interceptor ServicePermissionCheckInterceptor
.
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 may also find it helpful to have an understanding of the predefined authentication policies supported by Oracle WSM. For more information, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.
Complete this task:
Grant users access to the service, as described in Section 11.2.16, "How to Grant Test Users Access to the Service."
To configure an authentication and authorization:
In the Application Navigator, expand the application module, expand the serviceinterface node, 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
.
In the source for the remote server class, place your cursor on the @PortableWebService
annotation.
For example, StoreFrontServiceImpl.java
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") ...
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.
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.
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/wss11_saml_or_username_token_with_message_protection_service_policy in the dialog, the following @SecurityPolicy
annotation and @CallbackSecurityPolicy
(for asynchronous service) 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/wss11_saml_or_username_token_with_message_protec tion_service_policy" }) @CallSecurityPolicy("oracle/wss11_saml_or_username_token_with_message_protec tion_service_policy") ...
If your services will always be invoked exclusively through SOAP (and not RMI), you should use an Oracle WSM authorization policy as follows:
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.
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.
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" })
If your services will be invoked through SOAP and RMI, you should use ServicePermissionCheckInterceptor
only (there is no need to use an Oracle WSM authorization policy) as follows:
In the source editor, place your cursor in the @Interceptors
annotation and add ServicePermissionCheckInterceptor.class
to enable permission checking at runtime.
... @SecurityPolicy( { "oracle/wss11_saml_or_username_token_with_message_protection_service_policy" }) @CallSecurityPolicy("oracle/wss11_saml_or_username_token_with_message_protection_service_policy") @Interceptors({ServiceContextInterceptor.class, ServicePermissionCheckInterceptor.class})
Save the remote server class file.
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.
To secure the web service for RMI clients:
Configure JNDI context properties to enable authentication.
Enable permission checking to configure an authorization policy.
It may be helpful to have an understanding of the predefined authorization policies supported by Oracle WSM. For more information, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.
When the ADF web 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 theconnections.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.
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."
To configure JNDI context properties to handle authentication:
In the Application Navigator in the Application Resources panel, expand the Descriptors and ADF META-INF nodes, and then double-click the connections.xml
file.
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>weblogic</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>
Save the file.
You can enable permission checking to allow only users with sufficient privileges to invoke a service method on the service interface. In order to enable permission checking, the ADF service interface 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
.
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 may also find it helpful to have an understanding of the binding_permission_authorization_policy
authorization policy supported by Oracle WSM. For more information, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.
Complete these tasks:
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."
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:
In the Application Navigator, expand the META-INF node of the web service project and double-click the ejb-jar.xml node.
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>
In the Application Navigator, expand the application module, expand the serviceinterface node, and then double-click the remote server class (AppModuleServiceImpl.java) node.
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})
Save the files.
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.
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.
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 may also find it helpful to have an understanding of application roles and the OPSS security provides. For more information, see the Oracle Fusion Middleware Security Guide.
Complete these tasks:
Configure authentication and authorization policies for your service, as described in Section 11.2.14, "How to Secure the ADF Web Service for Access By SOAP Clients," or Section 11.2.15, "How to Secure the ADF Web Service for Access By RMI Clients."
Add the OPSS security provider configuration file to your project by creating a jazn-data.xml
deployment descriptor. For more information about deployment descriptors, see the "Deploying Applications" chapter in the Oracle Fusion Middleware User Guide for Oracle JDeveloper.
Note that in JDeveloper you open the New Gallery, expand General, select Deployment Descriptors and then Oracle Deployment Descriptors, and click OK.
Create the desired application roles that you want to make grants to, as described in Section 35.4, "Creating Application Roles."
For the purpose of testing your web service in JDeveloper using Integrated WebLogic Server, you can populate the application roles with test users, as described in Section 35.6, "Creating Test Users."
To grant the web service permission to application roles in the jazn-data.xml file:
From the Application menu, choose Secure > Resource Grants or choose Secure > Entitlement Grants.
You can grant multiple privileges to an application role as an entitlement set or you can grant individual privileges to a resource. Create an entitlement grant to aggregate privileges that together secure a specific end user duty. For details about entitlement grants, see Section 35.5.11, "How to Aggregate Resource Grants as Entitlement Grants."
In the editor window for the jazn-data.xml
file, select the Source tab.
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.
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 under the serviceinterface node to view thename
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
.
Save the changes to the jazn-data.xml
file.
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.
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."
To enable support for sending binary data attachments:
In the Application Navigator, expand the application module, expand the serviceinterface node, 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
.
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") ...
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 ...
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:
In the Application Navigator, expand the application module, expand the serviceinterface node, 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
.
Right-click the remote server class file, and choose Run or Debug.
The Configure Default Domain dialog displays the first time you run the application and start a new domain in Integrated WebLogic Server. Use the dialog to define an administrator password for the new domain. Passwords you enter can be eight characters or more and must have a numeric character.
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.
Tip:
In the Log window, you can click the target URL link to launch the HTTP Analyzer. This is a convenient shortcut for testing with JDeveloper Integrated WebLogic Server. For more information about the HTTP Analyzer, see the "Auditing and Profiling Applications" chapter in the Oracle Fusion Middleware User Guide for Oracle JDeveloper.Copy the target URL (beginning with http://
) from the Log window.
For example, if the Log window displays:
http://<
ipaddress
>/ADFServiceDemo-ADFModel-context-root
Integrated WebLogic Server will display the service endpoint URL. So there is no need to append the service name.
Launch a web browser, paste the target URL you copied from the Log window into the browser address field, and submit the HTTP request.
In the test page, choose the operation you want to invoke from the Operations dropdown list and enter sample data in its parameter fields.
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.
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 can 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. JDeveloper updates the method by adding the annotation @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
.
Example 11-13 NOT_SUPPORTED Annotation in Custom Service Method
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void updateCustomerInterests(List<String> pCategoryIds) throws ServiceException { invokeCustom((Method) _map.get("updateCustomerInterests"), new Object[] { pCategoryIds }, new String[] { null }, false); }
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, as Example 11-14 shows, the methods of the implementation class of the application module that you service-enabled, will need to call am.getDBTransaction().commit()
or rollback()
in order to complete the transaction.
Example 11-14 Custom Code to Handle Transaction Execution in Implementation Method
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; } }
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.
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."
To prevent custom methods from executing in a JTA transaction:
In the Application Navigator, expand the application module, expand the serviceinterface node, 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
.
In the source editor, locate the custom method that you want to prevent from timing out and place your cursor on the method.
In the Property Inspector, expand Stateless Session Bean and choose TransactionAttributeType.NOT_SUPPORTED from the TransactionAttribute dropdown list.
As shown in updateCustomerInterests()
in Example 11-13, JDeveloper updates the custom service method with the annotation.
Save the remote server class.
In the Application Navigator, double-click the application module implementation class (AppModule
Impl.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
.
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.
As Example 11-14 shows, 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.
Save the application module implementation class.
You can deploy the web service to Oracle WebLogic Server, for example to perform a second stage of testing the service.
If your project contains a standard web service (a Java class or interface with the @WebService
annotation), you must remove the @WebService
annotation from the Java class before you can deploy the Business Components web service. If you attempt to deploy the Business Components web service from the same project as the standard web service, deployment will fail with an an Oracle WebLogic Server exception error. It is therefore necessary to create standard web services in a separate project from your ADF Business Components service.
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.
If you configured authorization for the web service as described in Section 11.2.14, "How to Secure the ADF Web Service for Access By 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 nodes.
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>
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 node 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:
Create an application server connection to Oracle WebLogic Server:
From the main menu, choose View > Application Server Navigator.
In the Application Server Navigator, right-click the Application Servers node and choose New Application Server, and complete the Create Application Server Connection wizard.
Create a service deployment profile:
In the Application Navigator, right-click the project contain the web service and choose Project Properties.
In the Project Properties dialog, open the Deployment page and click New.
In the Create Deployment Profile dialog, choose Business Components Service Interface as the archive type, as shown in Figure 11-11.
From the Application menu, choose Deploy > deployment profile for the deployment profile you created.
In the Deploy wizard, on the Deployment Action page, select Deploy to Application Server and click Next.
On the Select Server page, select the application server connection.
Click OK.
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.
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:
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.
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.
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."
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:
In the Application Navigator, right-click the project in which you want to create the entity object and choose New.
In the New Gallery, expand the Business Tier node, select ADF Business Components and then Entity Object, and click OK.
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.
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.
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.
Click Finish.
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. You cannot make existing view objects service-backed. Instead, when you create the view object, the new view object will automatically be service-backed if its entity usage is a service-backed entity object.
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:
In the Application Navigator, right-click the service-backed entity object and choose New Default View Object.
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."
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-15.
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-15 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>
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."
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."
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:
Add the bcProfileName
_Common.jar
file for the SDO's generated classes to the client project's classpath.
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).
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 and their schema definitions 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:
In the Application Navigator, right-click your project node and choose Project Properties.
In the Project Properties dialog, select Libraries and Classpath and click Add Libraries.
In the Add Library dialog, click New to create the SDO client library.
In the Create Library dialog, click Add Entry to add a classpath entry.
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.
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.
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-16. 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 theconnections.xml
file. For instructions, refer to the online documentation in Oracle Enterprise Manager.Example 11-16 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-17:
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-17 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-17 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>
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 theconnections.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-18 or Example 11-19. 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-18.
Note:
Theconnections.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-18 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-19.
Example 11-19 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>
When the service endpoint provider is 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 theconnections.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-20, where fabricAddress
is the name of the Fabric composite for the published service.
Example 11-20 Client connections.xml File Registers the Remote Business Components Service for the SOA Fabric SDO Binding
<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>
Before you can launch the Oracle ADF Model Tester, your project must meet the runtime requirements as described in Section 11.3.4, "How to Configure the Service-Backed Business Components Runtime." The Oracle ADF Model Tester 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 tester. If the endpoint is unavailable at the time you select the service-backed view object in the Oracle ADF Model Tester, you will get a runtime exception.
For details about running the Oracle ADF Model Tester, see Section 6.3.1, "How to Run the Oracle ADF Model Tester."
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.
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-21 shows, when you invoke the operation, you perform the following tasks:
Import the oracle.jbo.client.svc.ServiceFactory
class and published service class.
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.
Call create()
on a data factory object, where the proxy object is obtained from the getServiceProxy()
call.
Invoke the operation on the proxy object and return a data object.
Save the data object return as XML.
Example 11-21 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); }
The ADF service interface framework defines a set of common data objects, such as oracle.jbo.common.service.types.FindCriteria
, oracle.jbo.common.service.types.FindControl
, oracle.jbo.common.service.types.ProcessControl
, and so on. Those data objects are used in standard findXxx()
method and processXxx()
method calls. You can create these data objects in the consuming application and pass them to the standard service methods. As Example 11-22 shows, you can need to call the data factory class' create()
method to construct those data objects before passing them into the findXxx()
or processXxx()
methods.
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.
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."