Using Web Services with Complex Return Types in ADF

An Oracle JDeveloper Article
Written by Frank Nimphius, Oracle Corporation
July 2007

1.0 Introduction
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
4.0 Summary

1.0 Introduction

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. departmentId, departmentName, locationId, or 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.

  • If the data returned from the Web Service can be displayed directly in ADF with no additional pre-processing of the data required, then the Web Service Data Control represents a good choice. This option also is good to use for EJB 3.0 based Web Services.
  • If the returned data needs to be processed before it can be displayed, however, then the Web Service Proxy in combination with a JavaBeans facade is the natural choice. The returned data would need to be preprocessed, for example, when it is returned by a filter method that exposes the data based on a provided condition or when, in a master-detail scenario, the master object contains a list of detail objects that should be displayed in a separate detail page.

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.

2.0 Using Web Service Data Controls

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.

2.1 Creating a Web Service Data Control in Oracle JDeveloper

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.

2.2 Creating a JavaBean stub for the complex return type

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.

Building a JavaBean based on the definitions found in the WSDL file

As shown, the Departments object contains the following attributes: departmentName of type string, departmentId of type long, managerId of type long, and 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 java.lang.String and java.lang.Long.

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 General node.

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.

Generating a JavaBean by creating a Web Service Proxy

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.

 

2.3 Modifying the Web Service Data Control

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.

 

3.0 Using Web Service Proxies with JavaBeans 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.

3.1 Creating a POJO facade to expose Web Service Proxy methods

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.

3.2 Creating a Data Control for Web Services that return complex types containing nested objects

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 Departments object.

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: getDepartments and getEmployees.

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.

4.0 Summary

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.

false ,,,,,,,,,,,,,,,