An Oracle JDeveloper Article
Written by Frank Nimphius, Oracle Corporation
2.0 Using Web Service Data Controls
2.1 Creating a Web Service Data Control in Oracle JDeveloper
2.2 Creating a JavaBean stub for the complex return type
2.3 Modifying the Web Service Data Control
3.0 Using Web Service Proxies with JavaBeans Data Controls
3.1 Creating a POJO facade to expose Web Service Proxy methods
3.2 Creating a Data Control for Web Services that return complex types containing nested objects
In her blog posting
Dealing with Complex Input Params in ADF Web Service Data Controls, Susan Duncan from the Oracle JDeveloper team showed how to handle complex input parameters when calling Web Services from Oracle ADF. A complex parameter can be a custom bean like Departments, which wraps a number of attributes, e.g.
managerId. In her blog, Susan explains how to create an instance of the complex input type in a managed bean and how to add it to the parameter map of an Oracle ADF operation binding that calls the Web Service. This approach works very well when the complex type is passed to the Web Service as an argument.
But what happens when the information to be displayed is returned as a complex type from Java EE and EJB 3.0 Web Services? When this is the case, there are two possible solutions:
A Web Service Data Control - the Web Service Data Control creates JSR-227 compliant metadata from the Web Services definition, which doesn't include generating the bean classes for the complex types. The metadata is interpreted by the Web Service Data Control at runtime. Because only metadata is generated by the Web Service Data Control, the beans representing the complex data types must be provided by the developer.
A Web Service Proxy - the Web Service Proxy generates a Java client from the Web Service's WSDL file. The WSDL file is an XML-formatted ASCII file that defines method signatures and returns the data structures of a Web Service independent of implementation. Web Service consumers use the WSDL file to learn how to invoke a Web Service method and how to handle the expected results, if any. The Web Service Proxy generates all the required classes, including the JavaBean representations of the complex types used. Web Service Proxies can be exposed to ADF directly or through a POJO facade, using the JavaBeans data control.
With two similar solutions available, the question of which to use when naturally arises.
This article examines both methods of using Web Services in ADF: Web Service Data Controls and Web Service Proxies. Note that these are advanced topics. This document does not address the general use of Web Services in ADF.
The following screenshot shows two sample projects in Oracle JDeveloper, used for illustration only. The WebServices model project holds the Web Service Data Control that references the WSDL file of the remote Web Service. The WebServicesADFApp project is a JavaServer Faces project that references the Web Service Data Control to render the returned data in a table.
Note: If you using a version of JDeveloper earlier than 10.1.3.3, such as 10.1.3.2 or 10.1.3.1, be aware of bug 5376910, which reports the improper handling of Java EE Web Services that return null values. If you cannot upgrade to JDeveloper 10.1.3.3, consider using a Web Service Proxy with a JavaBeans Data Control. This bug does not affect EJB 3.0–generated Web Services.
To create a Web Service Data Control in Oracle JDeveloper, you select the model project and choose New from the right-mouse context menu. In the New Gallery, select the Web Services entry under the Business Tier node. From the list of available items, select the Web Service Data Control entry.
In step 1 of the Create Web Service Data Control wizard, you define a name for the data control and provide the absolute URL for the Web Service WSDL file. If you use a Web Service deployed to Oracle Application Server or OC4J, then the root URL of the WSDL file can be copied from the Web Services tester in Enterprise Manager. To build the WSDL reference from this URL, append ?WSDL to the root URL and paste the string into the Web Service Data Control URL field. You can use the browse button if the WSDL file is located in the desktop's local file system.
In step 2 of the Create Web Service Data Control wizard, you can select the Web Service methods that should be exposed through the data control.
When you finish the wizard, the JDeveloper project is populated with the Web Service Data Control metadata files. Each of the exposed Web Service methods is represented by an XML file, e.g., findAllDepartments.xml. Under the package name built out of the data control name and the exposed method, RemoteWebService1.findAllDepartments in this example, there are three metadata files that describe the expected result collection of the Web Service request: item.xml, result_Operation.xml, and result.xml.
The preceding screenshot shows the generated metadata files, as well as their representation in the Data Control Palette at design time. As you see, the expected return type is shown as item, a Java object, rather than as a list of attributes. This is because the Web Service Data Control has no means of resolving the complex type contained in the Java EE Web Service response. To display the list of contained attributes, the application developer needs to provide a JavaBean representation, a Java class with the expected attribute names and types, that resolves the complex type.
Note: If your Web Service is an EJB 3.0 Web Service based on the JSR-181 library, then you don't need to provide this JavaBeans class. The ADF Web Service Data Control knows how to resolve the complex type and displays the contained attributes in the Data Control Palette.
There are two options available to you for creating the JavaBean representing the complex type: building the JavaBean manually by reading the content of the WSDL file or generating the JavaBean automatically through creating a Web Service Proxy.
As shown, the
Departments object contains the following attributes:
departmentName of type
departmentId of type
managerId of type
locationId of type
long. The data types are not Java-specific but generic, which means that you need to find the equivalent Java types when building the bean representation. The equivalent Java types in this case are
To create the bean, create a new Java class in JDeveloper and give it the name of the complex type:
Departments. To create the class, select the model node and choose
New from the right-mouse context menu. In the New Gallery, select
Java Class under the
In the Java source editor, create private member variables with the names and types found in the WSDL file. Make sure that the class implements
java.io.Serializable so that the object can be serialized when submitted by the Oracle ADF application. To create the setter and getter methods, right-click in the source editor and choose
Generate Accessors from the context menu.
Save and compile the Java class.
Reading the WSDL file to manually create the JavaBean stub may not be everybody's taste. A simpler and less error-prone option for creating the JavaBean representation of the complex return type is to create a Web Service Proxy in a separate project. As part of the Web Service Proxy creation, a JavaBean file is created for the complex return type. This file can be moved from the Web Service Proxy project to the Web Service Data Control project using drag and drop.
To build a Web Service Proxy, create a new JDeveloper project for the Web Service Proxy and choose New from the right-mouse context menu. Under Business Tier | Web Services, select the Web Service Proxy entry.
In the first step of the wizard, provide the absolute URL to access the remote WSDL file in the URL field. Continue and finish the wizard, selecting the Web Service methods to be exposed. This generates all the Java classes required to work with the Web Service.
As shown in the following screenshot, the classes that represent the complex return types can be accessed from the Structure window when the Web Service Proxy entry is selected in the Application Navigator. To proceed from here, you can either create a dependency of the model project to the Web Service Proxy project and reference the
Departments class from the Web Service Data Control's
result.xml file, or copy and paste the file content into a class of the same name in the model project. If not referenced, the Web Service Proxy project can be deleted afterwards.
With the JavaBean file created, the Web Service Data Control needs to be updated with a reference to it. In the JDeveloper Application Navigator, select the result.xml file under the <DataControl Name>.<Method Name> node and open the Structure window (Ctrl+Shift+S). Select the item entry in the Structure window and double-click it to open the attribute editor. In the Attribute Attribute Editor dialog, select the Accessor Attribute entry and click the Browse button next to the Bean Class field. Use the class browser to search for the bean class you created earlier. In this example, the bean class is Departments, located in the adf.sample package.
Save the changes and refresh the Data Control Palette in the view layer project. To refresh the Data Control Palette, right-click in the palette and choose Refresh from the context menu.
The Data Control Palette now shows the attributes contained in the complex result. Dragging the item entry onto a JavaServer Faces page or an ADF Swing panel brings up the table binding editor for the application developer to choose which attributes to display in the page.
At runtime, both the ADF Faces and the ADF Swing tables show the data retrieved from the Web Service as if it were queried from, for example, EJB, ADF Business Components, or POJO. To update a selected table row, have a look at Susan Duncan's blog how-to Dealing with Complex Input Params in ADF Web Service Data Controls.
The second approach to integrate Web Services with Oracle ADF is through Web Service Proxy classes. You can either directly create a JavaBeans data control from the generated Web Service Proxy client, or you can create a POJO facade to expose selected methods of the Web Service Proxy only. The latter option, creating a POJO facade to expose Web Service Proxy methods, is explained here in detail.
As shown previously, the Web Service Proxy is generated by Oracle JDeveloper based on the WSDL file definition. To generate the proxy, create a new project and choose New from the right-mouse context menu. In the Business Tier section, select the Web Services entry and choose Web Service Proxy. Follow the Create Web Service Proxy wizard and provide a reference to the WASL file that describes the Web Service.
When you finish the wizard, the Web Service Proxy is created. It contains generated JavaBeans classes for the complex custom return types. To create a POJO facade, create a new Java class in the project. Within the Java class, access the generated Web Service Proxy client to gain a handle to the Web Service. In the sample POJO shown below, the
findAllDepartments() method is called on the Web Service Proxy and the returned data exposed through a public get method. Note that the return type of the
getDepartments() method is
List<Departments>, which is a typed list. This way, ADF knows how to resolve the data type when building the JavaBeans data control.
To build the JavaBeans data control, right-click on the POJO facade and choose Create Data Control from the menu. This creates all the required metadata files for the data control.
Opening the Data Control Palette in the ViewLayer project shows the list of departments.
So far, this paper covered the handling of Web Services that return complex types in ADF. A specific usecase of using a Web Services proxy class is when the Web Service returns an object that itself contains a list of objects, as in a master-detail behavior. For example, the
Departments object could contain a list of
Employees objects. This use case is best handled with the combination of a Web Service Proxy and a POJO facade, exposed through a JavaBeans data control.
The Web Service Proxy class can be created as explained in
Using Web Service Proxies with JavaBeans Data Controls. The difference is that the POJO session facade exposes a method that returns a list of
Employees objects for a specific
As shown in line 40, the
Departments object is provided as the input argument for the
getEmployees() method. Creating a Data Control from such a POJO facade exposes two methods to ADF:
The departments table is built from dragging the
getDepartments method onto the JSF page. To query the detail records for a department, drag a
SetActionListener component from the ADF Faces Core library in the Component Palette onto the command component. Use the
SetActionListener component to store the selected row object in the session so that it becomes available on the detail page. For the selected table row, the departments object can be accessed through the ADF binding using Expression language, as shown in the following screenshot.
To create the detail page, drag and drop the
getEmployees method onto the JSF page and bind the input argument to the departments object stored in the session. In the following example, the departments object is stored in the "rowObj" session attribute, where it can be accessed with Expression Language.
To update a Web Service with an object that contains a nested list of detail objects, refer to Dealing with Complex Input Params in ADF Web Service Data Controls.
This how-to document explains how complex and custom objects returned by a Web Service method can be displayed on a web page using either an Oracle ADF Web Service Data Control or a JavaBeans data control accessing a Web Service Proxy. Which approach to use for a given ADF application development project depends on the specific requirements of that project. If a Web Service can be used as is, then the Web Service Data Control represents the natural choice. However, if the data returned by the Web Service needs to be preprocessed before display, then a Web Service Proxy class becomes the better choice.