Oracle® Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework 11g Release 1 (11.1.1) B31974-06 |
|
![]() Previous |
![]() Next |
This chapter describes how to publish ADF application modules to make them available as external services in a composite Fusion web application, and how to incorporate the published application module as an external service in the composite Fusion web application.
This chapter includes the following sections:
Section 11.1, "Introduction to Service-Enabled Application Modules"
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 that might be installed at runtime in a separate application server.
Note: For background about web services and Oracle WebLogic Server support for web services, see Oracle Fusion Middleware Introducing Web Services. |
Service Component Architecture (SCA) provides an open, technology-neutral model for implementing remotable services that are defined in terms of business functionality and that make middleware functions more accessible to application developers. ADF Business Components supports an SCA-compliant solution through application modules you can publish with a service interface. Any development team can publish a service-enabled application module to contribute to the composite Fusion web application. The Fusion web application assembled from remote services also does not require the participating services to run on a single application server.
Although composite applications often run on separate application servers, the appearance that SCA provides is one of a unified application. Consuming client projects use the ADF service factory lookup mechanism to access the data and any business methods encapsulated by the service-enabled application module. At runtime, the calling client and the ADF service may or may not participate in the same transaction, depending on the protocol used to invoke the service (either SOAP or RMI). Only the RMI protocol and a Java Transaction API (JTA) managed transaction support the option to call the service in the same transaction as the calling client. By default, to support the RMI protocol, the ADF service is configured to participate in the same transaction.
When you service-enable your application module, JDeveloper generates the necessary artifacts comprising: 1) The Java interface defining the service, 2) an EJB 3.0 session bean that implements this Java interface, 3) a WSDL file that describes the service's operations, and (4) an XML Schema Document (XSD) that defines the service's data structures. The service interface is described for Fusion web application clients in a language-neutral way by the combination of WSDL and XSD.
Note: SCA defines two kinds of service:
ADF Business Components services fall into the first category, and should only be used as remoteable services. For local service support, use the ApplicationModule interface and ViewObject interface support described in Section 9.10, "Working Programmatically with an Application Module's Client Interface." |
Services, including data access and method calls, defined by the remote application modules are interoperable with any other application module. This means the same application module can support interactive web user interfaces using ADF data controls and web service clients.
The common mechanism for invoking components such as a BPEL process is used by the ADF connection architecture to invoke a replaced service implementation (see Section 13.2, "Calling a Web Service from an Application Module") and a generic web service provider handles any application invocation that takes DataObject
arguments and returns DataObject
.
For information about the SCA and SDO standards, see the Open SOA web site at http://www.osoa.org
.
The application module is ADF Business Components framework component that encapsulates business logic as a set of related business functions. Application modules are mapped to services. You use the overview editor for your application module to enable a web service interface and publish rows of view object data as Service Data Object (SDO) components. The SDO framework upon which these components are based abstracts the data of the view object and standardizes the way that data structures are passed between Java and XML. This data abstraction simplifies working with heterogeneous data sources in a service-oriented architecture (SOA) and lets you selectively service-enable view objects using the same view object to support interactive web user interfaces and web service clients.
JDeveloper allows you to expose application modules as web services which use SDOs to standardize the way that data structures are passed between Java and XML. JDeveloper also generates the WSDL service description that is used by the web service client in the consuming application.
The service-enabled application module exposes the view objects, custom methods, built-in data manipulation operations, and specialized find methods based on named view criteria to be used by the client. Once you have enabled the application module service interface, you will need to create an ADF Business Components Service Interface deployment profile and deploy it to the target application server.
You can also expose the service 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 view 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 view operations. Table 11-1 shows the list of standard operations that service view instances support.
Table 11-1 Service View Instance 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.7, "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 enable the service interface on a parent view object, JDeveloper automatically enables the service interface for view instances that extend the parent in a polymorphic collection. For details about polymorphic view objects, see Section 39.6.5, "Working with Polymorphic View Rows." |
For information on how to create SDO classes to selectively service-enable child view objects, see Section 11.2.4, "How to Service-Enable Individual View Objects."
Before you begin:
Create the desired application module as described in Section 9.2.1, "How to Create an Application Module."
To create the web service:
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 service view instances that you enable, select Generate Control Hints Operation.
When you enable this option, the wizard adds the getDfltCtrlHints()
method to the service interface. The service interface client can invoke this method to resolve UI hints on the server without requiring a database roundtrip. The method takes the view object name and a locale and returns the base UI hints for that locale.
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 supported data types, such as a primitive Java type, oracle.jbo.server.ViewRowImpl
, java.util.List<ViewRowImpl>
, oracle.jbo.AttributeList
, or java.util.List<AttributeList>
.
Note that although both ViewRowImpl
and AttributeList
data types expose the identical row structure to the web service client, at runtime there will be a fundamental difference. For a description of the supported data types, see Section 11.2.3, "What You May Need to Know About Method Signatures on the Service Interface."
After selecting a qualifying custom method to appear in the service interface, for each parameter and return value using the ViewRowImpl
or AttributeList
data type, you must in turn select the name of the view object instance corresponding to the row structure:
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.
On the Service View Instances page, select the top-level view instances in the application module that you want to expose in the service interface.
View object subtypes of the top-level view instance will automatically be service-enabled.
Also, on this page, you can set the available data manipulation operations supported on the exposed methods, as shown in Figure 11-1.
In the Basic Operations tab, select the data manipulation operations for the currently selected view instance.
The primary purpose of the standard service view 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 view 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.7, "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 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.
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. This file appears in the Application Navigator in the Application Resources panel, under the Descriptors and ADF META-INF folders.
The remote common interface uses metadata annotations specified by the web service specification (JSR-181) to indicate how the interface should be exposed as a web service. This example shows part of StoreFrontService.java
, which is the remote common class for the StoreServiceAM
application module in the StoreFront module of the Fusion Order Demo.
Example 11-1 Remote Common Interface in Fusion Order Demo
package oracle.fodemo.storefront.store.service.common.serviceinteface; ... import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.soap.SOAPBinding; ... import oracle.fodemo.storefront.store.queries.common.CustomerInfoVOSDO; import oracle.fodemo.storefront.store.queries.common.OrderInfoVOSDO; ... import oracle.webservices.annotations.PortableWebService; import oracle.webservices.annotations.SDODatabinding; ... @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.WRAPPED, style=SOAPBinding.Style.DOCUMENT) @PortableWebService(targetNamespace="http://www.globalcompany.com/StoreFrontService", name="StoreFrontService", wsdlLocation= "oracle/fodemo/storefront/store/service/common/serviceinteface/StoreFrontService.wsdl") @SDODatabinding(schemaLocation= "oracle/fodemo/storefront/store/service/common/serviceinteface/StoreFrontService.xsd") public interface StoreFrontService { public static final String NAME = ("http://www.globalcompany.com/StoreFrontService") /** * @param orderId * @return * @throws ServiceException */ @WebMethod(action="www.globalcompany.example.com/getOrderInfoVOSDO", operationName="getOrderInfoVOSDO") @RequestWrapper(targetNamespace="www.globalcompany.example.com/types/", localName="getOrderInfoVOSDO") @ResponseWrapper(targetNamespace="www.globalcompany.example.com/types/", localName="getOrderInfoVOSDOResponse") @WebResult(name="result") OrderInfoVOSDO getOrderInfoVOSDO(@WebParam(mode = WebParam.Mode.IN, name="orderId") BigInteger orderId) throws ServiceException; ... }
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 ADF Business Components service factory is the mechanism that allows the service client to look up the service. The service factory relies on ADF connection architecture and the connections.xml
file to manage service endpoint locations. The connections.xml
file is created when you first create an ADF Business Components service. This file appears in the Application Navigator in the Application Resources panel, under the Descriptors and ADF META-INF folders.
Example 11-3 shows the initial connections.xml
entry created by JDeveloper when you first create an ADF Business Components service.
Example 11-3 connections.xml File Generated by JDeveloper
<Reference name="{http://www.globalcompany.com}StoreFrontService" className="oracle.jbo.client.svc.Service" xmlns=""> <Factory className="oracle.jbo.client.svc.ServiceFactory"/> <RefAddresses> <StringRefAddr addrType="serviceInterfaceName"> <Contents>oracle.fodemo.storefront.store.service.common.serviceinterface. StoreFrontService</Contents> </StringRefAddr> <StringRefAddr addrType="serviceEndpointProvider"> <Contents>ADFBC</Contents> </StringRefAddr> <StringRefAddr addrType="jndiName"> <Contents>oracle.fodemo.storefront.store.service.common. StoreFrontServiceBean</Contents> </StringRefAddr> <StringRefAddr addrType="serviceSchemaName"> <Contents>StoreFrontService.xsd</Contents> </StringRefAddr> <StringRefAddr addrType="serviceSchemaLocation"> <Contents>oracle/fodemo/storefront/store/service/common/ serviceinterface/</Contents> </StringRefAddr> </RefAddresses> </Reference>
You can define two different kinds of interfaces for an application module: the client interface and the service interface. The client interface is used by the ADF Model layer for UI clients. The service interface is for application integration and is used by external web services or other application services (either programmatically or automatically using the service-enabled entity feature).
An application module can support no interface at all, only client interfaces, only service interfaces, or both client interfaces and service interfaces combined. However, be aware that the two kinds of interfaces differ in the data types that are supported for the parameters and/or return values of your custom methods that you define for the respective interfaces. The types supported on the client interface are described in Section 9.9.5, "What You May Need to Know About Method Signatures on the Client Interface."
The service interface, in contrast to the client interface, supports a more narrow set of data types for custom method parameters and return values and is limited to:
Java primitive types and their object wrapper types (e.g. int
, Integer
)
java.lang.String
java.math.BigDecimal
java.math.BigInteger
java.sql.Date
java.sql.Time
java.sql.Timestamp
java.util.Date
oracle.jbo.AttributeList
oracle.jbo.domain.BlobDomain
oracle.jbo.domain.Char
oracle.jbo.domain.ClobDomain
oracle.jbo.domain.DBSequence
oracle.jbo.domain.Date
oracle.jbo.domain.NClobDomain
oracle.jbo.domain.Number
oracle.jbo.domain.Timestamp
oracle.jbo.domain.TimestampLTZ
oracle.jbo.domain.TimestampTZ
oracle.jbo.server.ViewRowImpl
or any subtype
java.util.List<
aType
>
, where aType
is any of the service-interface supported data types
You can define a custom method that returns a type of AttributeList
when you want the client developer to work with the list of service-enabled entity object or view object attributes to perform custom operations without the need to involve framework behavior before running the custom method. As an alternative, when the client developer wants the framework to manage rows (create, find, and populate), define custom methods that return ViewRowImpl
instead. In summary, if your method signature defines ViewRowImpl
as the data type, then the application automatically:
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.
Before you begin:
Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.2.3, "How to Create an Expert Mode, Read-Only View Object."
To set the SDO name and namespace for a view object:
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 that you can assign to group similar SDOs together by entering the same URI.
A default SDO namespace is created for you based on the SDO's package name with periods replaced by "/". If you have defined a prefix for the namespace in the View Objects page of the Preferences dialog, the prefix will be added at runtime to the beginning of the namespace. For example, Figure 11-7 shows the default namespace based on the package name.
Optionally, select Support Warnings when you want to be able to extract warnings associated with the view rows of the service interface object.
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 will not automatically be executed on the detail view object. You will need to enable support for nested processing for these methods in the service interface:
To support get and find methods that retrieve child details along with the parent, the view link between the master and detail view objects must have the destination accessor generated. The destination accessor permits traversal of the hierarchy from the master to the detail view object.
To support create/merge/update/process methods that post child details along with the parent, the custom property SERVICE_PROCESS_CHILDREN
must be defined in one of these two situations:
The view link is based on an association, and the association has the destination accessor generated, and the association has a custom property SERVICE_PROCESS_CHILDREN=true
defined.
The view link is not based on an association but has a custom property SERVICE_PROCESS_CHILDREN=true
defined.
Normally, post operations on the detail view object would only be supported when the primary entity object of the master view object is composed with the primary entity object of the detail view object. The custom property provides an alternative that makes it convenient to support nested processing for any view objects with a view link defined. You can define SERVICE_PROCESS_CHILDREN
as a custom property in the overview editor for either the view link or the view link's association (when present).
Before you begin:
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. For more information about view links, see Section 5.6, "Working with Multiple Tables in a Master-Detail Hierarchy."
If the view link is based on an association, then the destination accessor must be exist for the association's destination entity object. To generate one, use the Relationship page of the overview editor for the association. For more information about associations, see Section 4.3, "Creating and Configuring Associations."
To support nested processing in a master-detail hierarchy:
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 both display these same selections.
In the General page, expand the Custom Properties section, and then click Add Custom Property and enter SERVICE_PROCESS_CHILDREN
for the property and enter true
for the property value, as shown in Figure 11-8.
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
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 method to return a list of view rows (wrapped in service data objects) and a list of warnings associated with these view rows. You can use the generated method result interface to extract warnings and exceptions. Note that a service-enabled view object throws service exceptions rather than ADF Business Components exceptions (JboException
object). To remedy this, the service interface adapter attempts to reconstitute ServiceException
to JboException
, where possible.
The view object SDO result class, as shown in Example 11-6, is similar to the view row class.
Example 11-6 SDO Result Class Defines Methods to Get Warnings from List
package oracle.fodemo.storefront.store.queries.common; import oracle.sdo.SDODataObject; public class OrderInfoVOSDOResultImpl extends oracle.jbo.common.service.types.MethodResultImpl implements OrderInfoVOResult { public static final int START_PROPERTY_INDEX = oracle.jbo.common.service.types.MethodResultImpl.END_PROPERTY_INDEX + 1; public static final int END_PROPERTY_INDEX = START_PROPERTY_INDEX + 0; public OrderInfoVOResultImpl() {} public java.util.List getValue() { return getList(START_PROPERTY_INDEX + 0); } public void setValue(java.util.List value) { set(START_PROPERTY_INDEX + 0 , value); } }
The ADF service interface framework allows you to expose declarative find operations to execute the query define by a view object you select. However, when that query uses a bind variable to filter the query results, the bind variable must not be specified as Required and Updatable. Because the service interface does not expose required, updatable bind variables, a find operation that you execute for such a view object would fail to return any result.
When you want to filter a query result using bind parameters, use the view criteria and expose it as a find operation on the service interface. A service interface find operation based on a view criteria that you create can specify required bind variables.
Before you begin:
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 button.
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. For more information about programmatically filtering a query result, see Section 5.10.5, "How to Add a WHERE Clause with Named Bind Variables at Runtime."
Example 11-7 Find Method Added to Application Module Implementation Class
public class AppModuleImpl extends ApplicationModuleImpl { public List<ViewRowImpl> findProducts(String location) { List<ViewRowImpl> result = new ArrayList<ViewRowImpl>(); ViewObjectImpl vo = getProductsView1(); vo.setNamedWhereClauseParam("TheLocation", location); vo.setForwardOnly(true); vo.executeQuery(); while (vo.hasNext()) { result.add((ViewRowImpl)vo.next()); } return result; } }
Before you begin:
Create the custom application module class as described in Section 9.7.1, "How to Generate a Custom Class for an Application Module."
To expose a find method that sets a required bind variable:
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 button.
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 and select the View Criteria Find Operations tab and then click the Add View Criteria icon.
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.
For more information about invoking the web service using asynchronous request-response, see Oracle Fusion Middleware Concepts Guide for Oracle Infrastructure Web Services.
Before you can deploy an asynchronous web service, you must configure the queues used to store the request and response. For information about configuring the request and response queues, see the Oracle Fusion Middleware Concepts Guide for Oracle Infrastructure Web Services.
Before you begin:
Create the desired application module as described in Section 9.2.1, "How to Create an Application Module."
To expose asynchronous web service methods:
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 button.
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 the Business Components node 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 the Business Components node and choose Packages.
In the Relative Package Specification for Classes list, enter the default package name for the Service Interface Subpackage.
The default subpackage name is 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 the Business Components node 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. For information about the predefined policies supported by Oracle WSM, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.
You can enable authentication to require users to supply credentials before they have access to the service methods on the service interface. The type of authentication required is configured on the remote server class using an Oracle WSM authentication policy. For details about the available authentication policies, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.
To configure an authentication policy:
In the Application Navigator, expand the application module, expand the serviceinterface folder, and then double-click the remote server class (AppModule
ServiceImpl.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, StoreFrontService.wsdl
shows the annotation for the service as follows:
... @PortableWebService(targetNamespace="www.globalcompany.example.com", serviceName="StoreFrontService", portName="StoreFrontServiceSoapHttpPort", endpointInterface= "oracle.fodemo.storefront...common.serviceinterface.StoreFrontService") ...
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/wss_username_token_service_policy in the dialog, the following @SecurityPolicy
annotation would appear below the @PortableWebService
annotation:
... @PortableWebService(targetNamespace="www.globalcompany.example.com", serviceName="StoreFrontService", portName="StoreFrontServiceSoapHttpPort", endpointInterface= "oracle.fodemo.storefront.store.service.common.serviceinterface.StoreFrontService") @SecurityPolicy( { "oracle/wss_username_token_service_policy" }) ...
For details about configuring an authorization policy to require users to have sufficient access rights in order to invoke methods on the service, see Section 11.2.13.2, "Enabling Authorization for SOAP Clients."
Save the remote server class file.
You can enable permission checking to enable only users with sufficient privileges to invoke a service method on the service interface. This permission checking is configured on the remote server class using this Oracle Web Services Manager (Oracle WSM) authorization policy:
binding_permission_authorization_policy
This policy provides simple permission-based authorization for the request based on the authenticated Subject at the SOAP binding level. This policy ensures that the Subject has permission to perform the operation. This policy should follow an authentication policy where the Subject is established and can be attached to any SOAP-based endpoint.
As an alternative to the permission checking policy, you can configure one of these role-based Oracle WSM security policies:
binding_authorization_denyall_policy
This policy provides simple role-based authorization for the request based on the authenticated Subject at the SOAP binding level. This policy denies all users with any roles. It should follow an authentication policy where the Subject is established and can be attached to any SOAP-based endpoint.
binding_authorization_permitall_policy
This policy provides a simple role-based authorization for the request based on the authenticated Subject at the SOAP binding level. This policy permits all users with any roles. It should follow an authentication policy where the Subject is established and can be attached to any SOAP-based endpoint.
For further details about these authorization policy, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.
Before you begin:
Configure an authentication policy for the service, as described in Section 11.2.13.1, "Enabling Authentication for SOAP Clients."
Grant users access to the service, as described in Section 11.2.15, "How to Grant Test Users Access to the Service."
To configure a permission-based authorization policy:
In the Application Navigator, expand the application module, expand the serviceinterface folder, and then double-click the remote server class (AppModule
ServiceImpl.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, StoreFrontService.wsdl
shows the annotation for the service as follows:
... @PortableWebService(targetNamespace="www.globalcompany.example.com", serviceName="StoreFrontService", portName="StoreFrontServiceSoapHttpPort", endpointInterface= "oracle.fodemo.storefront...common.serviceinterface.StoreFrontService") ...
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" }) ...
For details about configuring an authentication policy to require the client to supply credentials in order to access the service, see Section 11.2.13.1, "Enabling Authentication for SOAP Clients."
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.
When the ADF service is invoked through RMI, authentication is handled with the common JAAS login module. The login module can be passed the principal and credential as part of the JNDI initial context for the EJB in the calling application. If you do not define the JNDI context properties, the login module will attempt to obtain the caller's current security context.
When you choose to define remote JNDI context information, then these four JNDI context properties need to be added to the connections.xml
file.
Note: When you intend to test the service in JDeveloper using Integrated WebLogic Server, before deploying the service you can edit the JNDI context properties in 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
should be composed as t3://
<hostname>
:
<server port>
.
For example, 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
is the user name who has permission to access the remote JNDI.
jndiSecurityCredentials
is the password for the security principal.
When you deploy to Integrated WebLogic Server in JDeveloper, you can enter the password in plain text. When you deploy the service to a standalone server, the password will not be read from the file. To configure the service password for standalone Oracle WebLogic Server, you must use Oracle Enterprise Manager.
To configure JNDI context properties to handle authentication:
In the Application Navigator in the Application Resources panel, expand the Descriptors and ADF META-INF folders, and then double-click the connections.xml
file.
In the source editor, add the JNDI context properties to specify the principal and credentials.
<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>weblogic</Contents> </StringRefAddr> <SecureRefAddr addrType="jndiSecurityCredentials"/> <Contents>weblogic1</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>
Save the file.
You can enable permission checking to enable only users with sufficient privileges to invoke a service method on the service interface. In order enable permission checking, the ADF web service framework provides an EJB interceptor named ServicePermissionCheckInterceptor
. This EJB interceptor ensures permission checking is enforced at runtime. Currently, the interceptor is configured to use the Oracle Web Services Manager (Oracle WSM) authorization policy binding_permission_authorization_policy
. For further details about this authorization policy, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.
Before you begin:
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.14.1, "Enabling Authentication for RMI Clients."
Grant users access to the service, as described in Section 11.2.15, "How to Grant Test Users Access to the Service."
To configure a permission-based authorization policy:
In the Application Navigator, expand the META-INF folder of the web service project and double-click the ejb-jar.xml
file.
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 folder, and then double-click the remote server class (AppModule
ServiceImpl.java
) file.
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. For more information about the OPSS security provider and application roles, see the Oracle Fusion Middleware Security Guide.
To configure the jazn-data.xml
file with test users that you can use to run the application in Integrated WebLogic Server, see Section 30.6, "Creating Test Users."
The invoke permission for Oracle Web Services is defined by the oracle.wsm.security.WSFunctionPermission
class. You can grant the invoke permission to the application roles you define for all the methods of the service or just to individual methods.
Before you begin:
Configure authentication and authorization policies for your service, as described in Section 11.2.13, "How to Secure the Web Service for SOAP Clients," or Section 11.2.14, "How to Secure the Web Service for RMI Clients."
Add the OPSS security provider configuration file to your project by creating a jazn-data.xml
deployment descriptor as described in "Creating and Editing a Deployment Descriptor" in the Deploying Applications section of the JDeveloper online help.
Note that in JDeveloper you open the New Gallery, expand General, select Deployment Descriptors and then Oracle Deployment Descriptors, and click OK.
Create the desired application roles, as described in Section 30.4, "Creating Application Roles."
For the purpose of testing your web service in JDeveloper, you can populate the application roles with test users, as described in Section 30.6, "Creating Test Users."
To grant the web service permission to application roles in the jazn-data.xml file:
From the Application menu, choose Secure > ADF Policies.
Before you begin this procedure, you need to create the application roles that you want to make grants to, as described in Section 30.4, "Creating Application Roles." If you are testing in JDeveloper, you can also populate the application roles with test users, as described in Section 30.6, "Creating Test Users."
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 in the serviceinterface folder 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.
To enable support for sending binary data attachments:
In the Application Navigator, expand the application module, expand the serviceinterface folder, and then double-click the remote server class (AppModule
ServiceImpl.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 folder, and then select the remote server class (AppModule
ServiceImpl.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.
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.
Copy the target URL (beginning with http://
) from the Log window.
Launch a web browser, paste the endpoint URL you copied from the Log window into the browser address field, append the service name, and submit the HTTP request.
For example, if the Log window displays:
http://130.35.103.93:8888/ADFServiceDemo-ADFModel-context-root
and the name of the service is AppModuleService
, the target URL would look like this:
http://130.35.103.93:8888/ADFServiceDemo-ADFModel-context-root/AppModuleService
In the test page, choose the operation you want to invoke from the Operations dropdown menu 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 could use the Administration Console for Oracle WebLogic Server to increase the JTA timeout setting. If you still receive a timeout exception or you anticipate that the custom methods of the service interface may be long running, you can specify an EJB transaction attribute for the stateless session bean to prevent the EJB from executing those methods in a JTA transaction.
To make a custom method exempt from timing out, you set TransactionAttributeType.NOT_SUPPORTED
in the Property Inspector specifically for that method. Because a method with this transaction attribute setting will not be executed in the JTA transaction, it is your responsibility to enforce control over the transaction using the ADF Business Components methods of the oracle.jbo.ApplicationModule
and oracle.jbo.Transaction
interfaces. For instance, on the methods of the implementation class of the application module that you service-enabled, you will need to call am.getDBTransaction().commit()
or rollback()
in order to complete the transaction.
You should not change the default transaction attribute setting for the standard service methods generated for the service interface (see Table 11-1). The standard methods will execute within the default execution boundary set for the JTA transaction.
To prevent custom methods from executing in a JTA transaction:
In the Application Navigator, expand the application module, expand the serviceinterface folder, then double-click the remote server class (AppModule
ServiceImpl.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 menu.
JDeveloper updates the method by adding the annotation @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
.
For example, for the custom service method updateCustomerInterests()
it would look like this:
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void updateCustomerInterests(List<String> pCategoryIds) throws ServiceException { invokeCustom((Method) _map.get("updateCustomerInterests"), new Object[] { pCategoryIds }, new String[] { null }, false); }
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.
For example, if you configured the TransactionAttribute property on the service method named updateCustomerInterests()
, then you would open the implementation class for the application module, locate the custom method updateCustomerInterests()
, and add am.getDBTransaction().commit()
and rollback()
as part of the method's try
and catch
statements like this:
public void updateCustomerInterests(List pCategoryIds) { try { if (pCategoryIds != null && pCategoryIds.size() > 0) { List<Integer> copyOfCategoryIds = (List<Integer>) this.cloneList(pCategoryIds); ViewObject selectedCategories = this.getSelectedCategoriesShuttleList(); RowSetIterator rsi = selectedCategories.createRowSetIterator(null); // remove rows for the current user not in the list of product keys while (rsi.hasNext()) { Row r = rsi.next(); Number interestId = (Number)r.getAttribute("CategoryId"); // existing row is in the list, we're ok, so remove from list. if (copyOfCategoryIds.contains(interestId)) { copyOfCategoryIds.remove(interestId); } // if the existing row is in not list, remove it. else { r.remove(); } } rsi.closeRowSetIterator(); // at this point, add new rows for the keys that are left for (int i =0 ;i < copyOfCategoryIds.size(); i++ ) { Row newRow = selectedCategories.createRow(); selectedCategories.insertRow(newRow); newRow.setAttribute("CategoryId", (String) copyOfCategoryIds.get(i).toString()); } this.getTransaction().commit(); } } catch (JboException e) { this.getTransaction().rollback(); throw e; } }
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. The procedure to deploy the web service will depend on whether or not you have enabled authorization for the web service. If you have enabled authorization, then preliminary steps to modify the web.xml
file in the packaged application's EAR file must be performed. These steps are required only if you have enabled an authorization policy, as described in Section 11.2.13.2, "Enabling Authorization for SOAP Clients."
Caution: Follow the procedure outlined in this section to modify theweb.xml of the packaged EAR file for a web service with authorization enabled, but do not use JDeveloper to deploy the EAR file since this will overwrite the web.xml file on the target server. Instead, use a tool like the Administration Console for Oracle WebLogic Server to manually deploy the packaged application's EAR file. For details about deploying secure web service applications outside of JDeveloper, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services. |
Before you begin:
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.13.2, "Enabling Authorization for SOAP Clients," edit the weblogic-application.xml
file to define application ID parameters. This file appears in the Application Navigator in the Application Resources panel, under the Descriptors and META-INF folders.
Add the following <application-param>
definition as the first element:
<weblogic-application xmlns="http://www.bea.com/ns/weblogic/weblogic-application"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://www.bea.com/ns/weblogic/weblogic-application.xsd">
<application-param>
<param-name>jps.policystore.applicationid</param-name>
<param-value>ApplicationName</param-value>
</application-param>
...
</weblogic-application>
Note that the ApplicationName
that you enter must match the name identified in the jazn-data.xml
policy store definition:
<jazn-data>
<policy-store>
<applications>
<application>
<name>ApplicationName</name>
<app-roles>
...
</app-roles>
<jazn-policy>
...
</jazn-policy>
</application>
</applications>
</policy-store>
</jazn-data>
Edit the ejb-jar.xml
file to add the following JpsInterceptor
definition required by the EJB for application roles evaluation. This file appears in the Application Navigator under the META-INF folder of the web service project.
<?xml version = '1.0' encoding = 'windows-1252'?>
<ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/j2ee/ejb-jar_3_0.xsd" version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee">
<enterprise-beans>
...
</enterprise-beans>
<interceptors>
<interceptor>
<interceptor-class>
oracle.security.jps.ee.ejb.JpsInterceptor
</interceptor-class>
<env-entry>
<env-entry-name>application.name</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>ApplicationName</env-entry-value>
<injection-target>
<injection-target-class>
oracle.security.jps.ee.ejb.JpsInterceptor
</injection-target-class>
<injection-target-name>
application_name
</injection-target-name>
</injection-target>
</env-entry>
</interceptor>
...
<interceptors>
<assembly-descriptor>
<interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>
oracle.security.jps.ee.ejb.JpsInterceptor
</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
</ejb-jar>
Note that ApplicationName
must also match the application name identified in the jazn-data.xml
policy store definition.
To deploy to Oracle WebLogic Server:
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 folder 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.
If you configured security for the web service using the Oracle WSM authorization policy for SOAP invocation as described in Section 11.2.13, "How to Secure the Web Service for SOAP Clients," deploy the web service to an EAR file so that you can manually edit the web.xml
file.
Note: If you did not configure security for the web service, you can skip this step and the manual editing tasks it describes. You can deploy the EAR as described in step 4.
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 EAR.
Click OK.
Locate the EAR file that JDeveloper creates for you. The file will appear in the deploy folder in your application's mywork folder. For example, if the application is named StoreFrontService
, the EAR file is found here:
C:\JDeveloper\mywork\StoreFrontService\deploy\StoreFrontServiceProject_bcprofile1.ear
Unjar this EAR file and locate the WAR file for the service interface project. For example, the WAR file might be named StoreFrontService-MiddleTier_web.war
.
Unjar the WAR file and locate the web.xml file in the WEB-INF folder. Extract the web.xml
file and add the following JPSWlsFilter
definitions:
<filter> <filter-name>JpsWlsFilter</filter-name> <filter-class>oracle.security.jps.ee.http.JpsFilter</filter-class> <init-param> <param-name>application.name</param-name> <param-value>ApplicationName</param-value> </init-param> </filter> <filter-mapping> <filter-name>JpsWlsFilter</filter-name> <servlet-name> ProjectName.server.serviceinterface.AppModuleServiceImpl </servlet-name> <dispatcher>REQUEST</dispatcher> </filter-mapping>
When you configure the JPSWlsFilter
, the application name value must match the application name set in jazn-data.xml
and weblogic-application.xml
files. For the filter mapping, enter the <servlet-name>
that will match the servlet name already present in your web.xml
. Note the filter name must match the filter name set for the JpsFilter
.
Repackage the modified WAR and EAR files with your edited file.
Do not use JDeveloper to deploy the EAR file since this will overwrite the web.xml
file on the target server. Instead, use a tool like the Administration Console for Oracle WebLogic Server to manually deploy the application EAR file. For details about deploying secure applications outside of JDeveloper, see the Oracle Fusion Middleware Security and Administrator's Guide for Web Services.
If you are deploying a web service EAR without configuring an Oracle WSM authorization policy for SOAP invocation, you can deploy the EAR file to Oracle WebLogic Server in JDeveloper:
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.
In a team development environment, teams can work independently to develop the web services (the service producer team) and the web application that will host these services (the service consuming team). In this scenario, the service consuming team does not use their application's Business Component Service deployment profile to generate the service's common.jar
and middletier.jar
files. Instead, the service producer team generates the service interface common JAR and implementation middletier EJB JAR files in their own application workspace. Then, the consuming team imports these JARs in a way that allows them to package the JAR files in their application's EAR file.
Before you begin:
Generate the common.jar
and middletier.jar
files in the service provider application, as described in Section 11.2.19, "How to Deploy Web Services to Oracle WebLogic Server." Use the Deploy to File option when you deploy the Business Component Service deployment profile.
Copy the two generated JAR files to a location that will allow the consuming application's developers to find them in the file system.
To host the service in a consuming application:
Add the service interface common.jar
as a dependent JAR file in one of the consuming application's projects:
In the Application Navigator, double-click the project in which you want to add the common JAR file.
In the Project Properties dialog, select Libraries and Classpath, then click Add JAR/Directory.
In the Add Archive or Directory dialog, open the directory that contains the service producer application's common.jar
file, select the JAR file, and click Select.
In the Project Properties dialog, click OK.
Create an application.xml
deployment descriptor file to include the middletier EJB JAR file:
In the Application Navigator, right-click the project in which you want to create the deployment descriptor and choose New.
In the New Gallery, expand Deployment Descriptors, select Java EE Deployment Descriptor and click OK.
In the Create Java EE Deployment Descriptor dialog, in the Select Descriptor page, select application.xml and click Finish.
In the Application Navigator, in the Application Sources/META-INF folder, double-click application.xml and click Finish.
<application ...>
<module>
<ejb>ImportedServiceMiddleTierJARName.jar</ejb>
</module>
</application>
Create the consuming application's EAR deployment profile and modify its profile properties:
In the Edit EJB JAR Deployment Profile Properties dialog, select File Groups and click New.
In the Create File Group dialog, name the file group Application Descriptors
, leave the default choice Packaging selected and click OK.
In the new file group, select Contributors and add the path to the middletier JAR file.
In the new file group, select Filters and include the middletier JAR (but do not include the common JAR file).
In the Edit EJB JAR Deployment Profile Properties dialog, select File Groups and click New.
In the Create File Group dialog, name the file group Application Libraries
, change the file group to Libraries selected and click OK.
In the new file group, select Filters and make sure that the common JAR file is included.
Click OK.
Deploy the EAR profile as the EAR file.
Oracle 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. In JDeveloper you cannot make existing view objects service-backed. Instead, when you create the view object in JDeveloper, the new view object will automatically be service-backed if its entity usage is a service-backed entity object.
Before you begin:
Create the service-backed entity object as described in Section 11.3.1.1, "Creating Entity Objects Backed by SDO Services."
To create a view object from the service-backed entity object:
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-10.
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-10 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 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.19, "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 folder 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-11. 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-11 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. When you intend to access the service in JDeveloper using Integrated WebLogic Server, you can edit these JNDI context properties in the connections.xml
file, as shown in Example 11-12:
jndiFactoryInitial
should be set to weblogic.jndi.WLInitialContextFactory
.
jndiProviderURL
should be composed as t3://
<hostname>
:
<server port>
.
For example, t3://localhost:8888
, where t3
is the Oracle WebLogic protocol, localhost
is the host name that the remote Oracle WebLogic Server instance runs in, and 8888
is the port number.
jndiSecurityPrincipal
is the user name who has permission to access the remote JNDI.
jndiSecurityCredentials
is the password for the security principal.
When you deploy to Integrated WebLogic Server in JDeveloper, you can enter the password in plain text. When you deploy the service to a standalone server, the password will not be read from the file. To configure the service password for standalone Oracle WebLogic Server, you must use Oracle Enterprise Manager. You should remove this JNDI property for standalone Oracle WebLogic Server.
Example 11-12 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>weblogic</Contents> </StringRefAddr> <SecureRefAddr addrType="jndiSecurityCredentials"/> <Contents>weblogic</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>
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, update the connections.xml
file following the example in Example 11-13.
soapWSDLUrl
is the URL of the published service's WSDL file.
For example, http://localhost:7101/StoreFrontService-StoreFront-context-root/StoreFrontService?WSDL
, where StoreFrontService
is the name of the Fusion Order Demo service.
soapPortName
is <serviceName>
SoapHttpPort
.
For example, StoreFrontServiceSoapHttpPort
, where StoreFrontService
is the name of the Fusion Order Demo service.
soapPolicyReferenceInfo
is the Oracle WSM security policy.
The connections.xml
file supports Oracle WSM security policy client overrides. For example, when the security policy is oracle/wss_username_token_client_policy
, the csf-key
property can be overridden to specify the consuming application's credentials.
Example 11-13 Client connections.xml File Registers the Remote Business Components Service for the SOAP Protocol
<References xmlns="http://xmlns.oracle.com/adf/jndi"> <Reference name="{www.globalcompany.com}StoreFrontService" className="oracle.jbo.client.svc.Service" xmlns=""> <Factory className="oracle.jbo.client.svc.ServiceFactory"/> <RefAddresses> <StringRefAddr addrType="serviceInterfaceName"> <Contents>oracle.foddemo.storefront.store.service.common. serviceinterface.StoreFrontService</Contents> </StringRefAddr> <StringRefAddr addrType="serviceEndpointProvider"> <Contents>SOAP</Contents> </StringRefAddr> <StringRefAddr addrType="soapWSDLUrl"> <Contents>http://localhost:7101/ADFServiceDemo-ADFModel-context-root/ AppModuleService?WSDL</Contents> </StringRefAddr> <StringRefAddr addrType="soapPortName"> <Contents>AppModuleServiceSoapHttpPort</Contents> </StringRefAddr> <XmlRefAddr addrType="soapPolicyReferenceInfo"> <Contents> <port-info> <stub-property> <name>csf-key</name> <value>my.credentials</value> </stub-property> <policy-references> <policy-reference uri="oracle/wss_username_token_client_policy" category="security"/> </policy-references> </port-info> </Contents> </XmlRefAddr> <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 Fabric, the service factory will return a 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-14, where fabricAddress
is the name of the Fabric composite for the published service.
Example 11-14 Client connections.xml File Registers the Remote Business Components Service for the SOAP Protocol
<References xmlns="http://xmlns.oracle.com/adf/jndi"> <Reference name="{www.globalcompany.com}StoreFrontService" className="oracle.jbo.client.svc.Service" xmlns=""> <Factory className="oracle.jbo.client.svc.ServiceFactory"/> <RefAddresses> <StringRefAddr addrType="serviceInterfaceName"> <Contents>oracle.foddemo.storefront.store.service.common. serviceinterface.StoreFrontService</Contents> </StringRefAddr> <StringRefAddr addrType="serviceEndpointProvider"> <Contents>Fabric</Contents> </StringRefAddr> <StringRefAddr addrType="fabricAddress"> <Contents>fabric_StoreFrontService</Contents> <StringRefAddr addrType="serviceSchemaName"> <Contents>StoreFrontAMService.xsd</Contents> </StringRefAddr> <StringRefAddr addrType="serviceSchemaLocation"> <Contents>oracle/fodemo/storefront/store/service/common/serviceinterface/</Contents> </StringRefAddr> </RefAddresses> </Reference> ... </References>
Before you can launch the Business Component Browser, your project must meet the runtime requirements as described in Section 11.3.4, "How to Configure the Service-Backed Business Components Runtime." The Business Component Browser will display the view objects you create from the remote service and allow you to interact with the service to perform standard CRUD operations.
Because the application module that you run can access locally queried data and remotely queried data together, service-backed view objects and database-derived view objects will display in the same Browser. If the endpoint is unavailable at the time you select the service-backed view object in the Business Component Browser, you will get a runtime exception.
For details about running the Business Component Browser, see Section 6.3.1, "How to Run the Business Component Browser."
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.
As Example 11-15 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 the in service name in the form <serviceName>
.NAME
.
Call create()
on a data factory object.
Invoke the operation on the proxy object and return a data object.
Save the data object return as XML.
Example 11-15 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) DataFactory.INSTANCE.create("http://example.com/hr/common/", "Dept"); dept.setDname("ENGINEERING"); ... dept = proxy.createDept(dept); String xml = XMLHelper.INSTANCE.save((DataObject) dept, "http://example.com/hr/common/", "dept"); out.print(xml); }
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."