Sie sind auf Seite 1von 28

Lesson 5

Create Service Consumer


Business Service

Objectives
By the end of this lesson, you will be able to:

 Generate a web service proxy

 Create a business service to wrap a web service proxy

 Create and retrieve a soft coding record

 Generate an XML template from a value object class

 Call a business service from a business function


______________________________________________________________________________________________________________

Activity Overview
EnterpriseOne consumes external web services through a web service proxy which is
called from a business service which is called from a business function. In this exercise
each of these elements will be created to call a weather forecast web service. The weather
forecast web service receives a US zip code as input and returns a one week forecast for
that location.

In this exercise the student will

 Create a business service from OMW

 Generate a web service proxy within JDeveloper

 Create an internal business service class that calls the web service proxy

 Use EnterpriseOne soft coding applications to create a soft coding record

 Add code to retrieve the soft coding record from within the business service

 Generate an XML template from a value object class

 Use the XML template as an example to write business function code which will
call the business service

PeopleSoft Proprietary and Confidential 1


Exercise Title <Lesson X.>

Note. This exercise closely mimics the Weather Forecast Processor Reference
Implementation, JRH90I10. Use the code in those objects as an example if necessary for
understanding.

2 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

Activity Detailed Steps

Configure JDeveloper for Web Service Consumption

To allow JDeveloper to retrieve external WSDL files configure preferences with HTTP
Proxy information.

1. Launch JDeveloper

2. From the Tools menu choose Preferences

3. Highlight Web Browser and Proxy

4. Configure JDeveloper to Use an HTTP Proxy Server with these settings

a. Host Name - www-proxy.us.oracle.com

b. Port Number – 80

c. Exceptions – Add these exceptions to the machine name already listed: |


*.oracle.com|*.peoplesoft.com|*.jdedwards.com|*.mlab.jdedwards.com

5. Press OK

6. Close JDeveloper

Create a business service from OMW

To add a new Business Service in Object Management Workbench:

7. Launch JD Edwards Solution Explorer

a. user name: JDE

Oracle Proprietary and Confidential 3


Exercise Title <Lesson X.>

b. password: JDE

8. Type OMW in the fast path field and press enter

9. Press Add

10. Select the Business Function radio button and press OK

11. Complete the following information about the published business service object

a. Object Name – J5500050

b. Description – Weather Forecast Processor

c. Product Code/Product System Code – 55

d. Source Language – BSSV

e. Package Prefix – oracle.e1.bssv

12. Press OK

13. Launch JDeveloper for the new business service

Generate a web service proxy within JDeveloper

Use native JDeveloper tooling to create a web service proxy for


http://www.webservicex.net/WeatherForecast.asmx.

1. With the project highlighted in the Application Navigator pane choose New from the
context menu.

14. In the New Gallery change the filter to All Technologies. Under Business Tier
choose Web Service. In the right hand pane choose Web Service Proxy. Press OK.

4 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

15. A multi-step wizard is shown. Click next past the welcome page. For step one
provide http://www.webservicex.net/WeatherForecast.asmx?wsdl as the WSDL
Document URL. Accept the defaults for the remainder of the wizard steps.

16. All classes necessary for invoking the web service will be generated and can be
viewed with the structure pane. When the wizard completes a
WeatherForecastSoapClient class will be opened in the editor. This is the class that
will be used to invoke the web service from the business service.

Oracle Proprietary and Confidential 5


Exercise Title <Lesson X.>

Create a business service class (and value object) that calls the web
service proxy

Use the EnterpriseOne extension to create an internal business service which will call the
web service proxy.

1. With the project highlighted in the Application Navigator pane choose New from the
context menu.

17. Select Classes under the EnterpriseOne heading then choose Business Service Class
in the right hand pane. Click OK.

18. Enter the following information about the business service class to be created:

a. Name – WeatherForecastProcessor

b. Method Name – getForecastByZip

c. Input Class (type this - class does not yet exist)


InternalGetWeatherForecast

19. In the method body declare an instance of the WeatherForecastSoapClient class. Add
the required try/catch block. Use the WeatherForecaseSoapClient instance variable to
add a call to GetForecastByZip.

try{
WeatherForecastSoapClient myPort = new WeatherForecastSoapClient();

myPort.getWeatherByZipCode()
}
catch (Exception e){
}

20. Ctrl-click on getWeatherByZipCode to see that its signature is:


WeatherForecasts getWeatherByZipCode(String zipCode) throws java.rmi.RemoteException

21. This signature will be used to help construct the value object for the business service.
First create the value object class. With the project highlighted, choose New from the
context menu.

22. Choose General on the left hand pane and Java class on the right. Press OK.

23. Give the new class the following values and press OK

a. Name – InternalGetWeatherForecast

b. Package – oracle.e1.bssv.J5500050.valueobject

c. Extends – oracle.e1.bssvfoundation.base.ValueObject

24. The new class is generated and opened. Add a string member variable for zip code.
Inspect the WeatherForecasts class to decide what other member variables should be
added to the value object class.

6 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

private String zipCode = null; // input


private String placeName = null; // output
private String stateCode = null; // output
private String status = null; // output

25. One of the values returned in the WeatherForecasts object is an array. To handle this
return value, another value object class must be created and added as a member
variable. With the project highlighted, choose New from the context menu.

26. Choose General on the left hand pane and Java class on the right. Press OK.

27. Give the new class the following values and press OK

a. Name – DayForecast

b. Package – oracle.e1.bssv.J5500050.valueobject

c. Extends – oracle.e1.bssvfoundation.base.ValueObject

28. Using the WeatherData class as a guide, add the following member variables to the
DayForecast object.

private String day = null;


private String maxTemperatureF = null;
private String minTemperatureF = null;
private String maxTemperatureC = null;
private String minTemperatureC = null;

29. Generate accessors for the WeatherData member variables.

30. Add an array of type DayForecast to the InternalGetWeatherForecast class.

private DayForecast[] details = null;

31. Generate accessors for the InternalGetWeatherForecast member variables.

32. Add logic to WeatherForecastProcessor.getForecastByZip to pass in the zip code and


to copy the values returned to the InternalGetWeatherForecast member variables.

WeatherForecasts wsReturn = myPort.getWeatherByZipCode(internalVO.getZipCode());
      
if (wsReturn != null)
{
  internalVO.setPlaceName(wsReturn.getPlaceName());
  internalVO.setStateCode(wsReturn.getStateCode());
  internalVO.setStatus(wsReturn.getStatus());
  WeatherData[] weatherData = wsReturn.getDetails();
  if (weatherData != null && weatherData.length > 0)
  {
    DayForecast[] dayForecast = new DayForecast[weatherData.length];
    for (int i = 0; i < weatherData.length; i++) 
    {
      dayForecast[i] = new DayForecast();
      dayForecast[i].setDay(weatherData[i].getDay());
      dayForecast[i].setMaxTemperatureC(weatherData[i].getMaxTemperatureC());
      dayForecast[i].setMaxTemperatureF(weatherData[i].getMaxTemperatureF());
      dayForecast[i].setMinTemperatureC(weatherData[i].getMinTemperatureC());

Oracle Proprietary and Confidential 7


Exercise Title <Lesson X.>

      dayForecast[i].setMinTemperatureF(weatherData[i].getMinTemperatureF());
    }
    internalVO.setDetails(dayForecast);
  }
}

33. Add logic to the catch block to report any exceptions that may occur. The string used
to construct the E1Message, “003FIS”, is an error data dictionary item. The
strMessage variable is substitution text added to the error.

String strMessage = new String("WeatherForecastProcessor.getForecastByZip|" + 
                         e.toString());

E1Message eMessage = new E1Message(context, "003FIS", strMessage);
//Add messages to final message list to be returned.
messages.addMessage(eMessage);

34. Compile (context menu > Make) the project and resolve any compile errors.

Create and retrieve a soft coding record

Soft coding records provide a means to dynamically provide endpoint and security
information to the third party web service. To create and use soft coding records:

1. Expand the ‘proxy’ package in the project and highlight the WeatherForecastProxy in
the Applications Navigator, choose Secure Proxy from the context menu

2. The wizard that is shown can be used to create soft coding records for any web
service proxy. Every supported standard is represented on the screens. For the
weather service, only the endpoint needs to be specified. On step 1 of 6, choose No
Authentication.

8 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

3. On step 2 of 6 uncheck Sign Outbound Messages

4. On step 3 of 6 uncheck Verify Inbound Signed Request Body

Oracle Proprietary and Confidential 9


Exercise Title <Lesson X.>

5. On step 4 of 6 uncheck Encrypt Outbound Messages

6.

7. On step 5 of 6 uncheck Decrypt Inbound Message Content

10 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

8. Click Finish. Open the resulting xml file by highlighting WeatherForecastProxy in


the Application Navigator and double clicking on WeatherForecastSoap_Stub.xml
in the structure pane.

Oracle Proprietary and Confidential 11


Exercise Title <Lesson X.>

9. Within the xml, look for the port-info tags. This xml element is the portion that is
used in a soft coding record. In this example where only endpoint is provided, the
significant information is in the wsdl-port tag. In a typical customer set-up, the wsdl-
port tag will need to contain different information in different environments.

10. For this particular web service only the endpoint really needs to be specified. Even
though all the ‘security’ options were disabled in the wizard the web service will give
a failure if the runtime tag is present in the XML. To avoid this error the runtime tag
must be removed. The resulting XML will contain:
<port­info>
<wsdl­port namespaceURI="http://www.webservicex.net" 
localpart="WeatherForecastSoap"/>
<operations>
<operation name='GetWeatherByZipCode'>
</operation>
<operation name='GetWeatherByPlaceName'>
</operation>
</operations>
</port­info>

This can be copied to the clipboard for use in the Soft Coding Application.

12 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

11. Go back to JD Edwards Solution Explorer and under Tools choose EnterpriseOne
Menu to launch the web version of the EnterpriseOne menu. Navigate to
EnterpriseOne Menus > EnterpriseOne Life Cycle Tools > System
Administration Tools > Soft Coding Administration and launch the Soft Coding
Template application.

12. Press Add

13. Add a Soft Coding template with the following values

a. Template Name – CUST_J5500050

b. SoftCoding Key – J5500050

c. Value – copy the <port-info> element from the generated xml document

35. Press OK. The significance of the soft coding template is the soft coding key, which
will be directly referenced in the code, and the structure of the xml. The template will
be used both by the developer in subsequent steps for the development environment,
and by system administrators for production environments.

36. Launch the Soft Coding Records application

37. Press Add

38. Enter values for these fields

d. User/Role – JDE

e. Environment – PD812

f. Template Name – CUST_J5500050

Oracle Proprietary and Confidential 13


Exercise Title <Lesson X.>

39. Press Populate Soft Coding Value to pull in the soft coding key and xml from the
template. At this point, if any information needed to vary based on user or
environment the xml would be changed as necessary. For this example, the
information from the template can be used as is.

40. Press OK

41. Return to JDeveloper. Open the WeatherForecastProcessor class and within the
getForecastByZip method locate the line declaring ‘myPort’. Place the cursor on the
line after the declaration.

42. Press Ctrl-Enter and highlight E1SC. Press Enter.

43. Type “J5500050” for the soft coding key.

44. Tab twice and replace BS_NAME with WeatherForecastProcessor

45. Tab and replace BS_METHOD_NAME with getForecastByZip

46. Tab twice to exit the code template edit mode.

47. Either restructure the nested try/catch blocks so that there is only one try/catch or
place a return statement within the soft coding catch block so that the service doesn’t
continue to run if a soft coding record is not found.

return messages;

48. Compile (context menu > Make) the project and resolve any compile errors.

14 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

Generate an XML template from a Value Object class

The business service which calls the web service is now complete. In order to test the
business service’s invocation of the web service, an XML document will be created.

1. Highlight InternalGetWeatherForcast.java in the Application Navigator choose


Generate XML Document Template from the context menu

49. An XML file will be created and opened that can be used as an example of how to
pass values from a business function to the business service. Choose Reformat from
the editor window’s context menu

50. Save a copy of this file (save as) with a different name to the same location on the
hard drive. Modify that copy of the file so it only contains the tags related to the input
(zip code). Put a value in for zip code. Save the file.
<?xml version="1.0" encoding="UTF­8"?>
<internal­get­weather­forecast>
  <zip­code>80134</zip­code>
</internal­get­weather­forecast>

51. By typing or using a code template (ctrl-enter) add a main method to the
WeatherForecastProcessor. Add a call to
TestBusinessService.callBSSVWithXMLFile. Use the available Javadoc to assist in
the correct values to pass (autoCommit can be true).

Oracle Proprietary and Confidential 15


Exercise Title <Lesson X.>

52. Run or debug the main method until the web service is called successfully.

53. Refresh the valueobject package of the project by highlighting it and pressing
“refresh”.

Results of the test will be written to the same folder as the input file. The output
comes in two files with the same prefix as the input file. The _messages file contains
the results of the call to the business service. If the call could not be competed, or
threw an exception of any kind it is captured in this text file. The _out.xml file
contains the results of a successful call to the business service. Be aware that calling
a business service successfully is not the same as a business service successfully
completing its task. The concept is the same as a business function returning success
which does not mean that the business function completed without errors.

54. Open the _out and _messages files which are now visible in the project to inspect the
results of the web service invocation. This is a significant development milestone
which proves that the business service is complete and correctly able to call the web
service.

Start the Development Business Services Server

To build and deploy the Development Business Services Server:

1. From the context menu of the workspace choose Deploy Development BSSV Server

16 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

55. Populate required information about HTTP Proxy server. A proxy server is a security
measure. All ‘outgoing’ traffic is routed through the proxy server. This is required so
that the business services server can call the web service. The same information was
configured for JDeveloper in the first section of this document.

a. Host Name: www-proxy.us.oracle.com

b. Port Number: 80

Oracle Proprietary and Confidential 17


Exercise Title <Lesson X.>

56. Press OK

57. Progress of the build and deploy scripts can be viewed in the Apache Ant tab.

Update a business function to call the business service

To update B5500050 to call getForecastByZip in J5500050:

1. From OMW search for B5500050 and add it to the default project

58. Press “Design” for the business function then Start Business Function Design Aid

59. Take the Form exit to Edit the business function

60. Within Visual Studio find the declaration for GetWeatherForecast.

61. Add variables and code to initialize the XML parser. Add associated import
statement.

#include <xerceswrapper.h>

XRCS_Status XRCSStatus = XRCS_SUCCESS;


XRCS_hParser hParser = NULL;

XRCSStatus = XRCS_initEngine();
if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_initEngine failed"));
return ER_ERROR;
}

/* Get the Xerces Parser */


XRCSStatus = XRCS_getParser(&hParser);
if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_getParser failed"));
XRCS_terminateEngine();
return ER_ERROR;
}

62. Add variables and code to declare and parse an XML string. The xmlString variable
is initialized based on the XML template generated from within JDeveloper (also
used for the test run). For more complex XML documents this can be constructed
dynamically if appropriate.

XRCS_hDocument hDoc = NULL;


JCHAR *xmlString = _J("<?xml version=\"1.0\"?
><internal-get-weather-forecast><zip-code></zip-code></internal-
get-weather-forecast>");

/* Parse the XML String */


XRCSStatus = XRCS_parseXMLString(hParser, xmlString, &hDoc);

18 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_parseXMLString failed"));
XRCS_freeParser(hParser);
XRCS_terminateEngine();
return ER_ERROR;
}

63. Add code and variables to locate and set the value of the zip code element.

XRCS_hElement hRootElm = NULL;


XRCS_hElement *hElm = NULL;
unsigned int nElmCount = 0;

/* Get Root Element */


XRCSStatus = XRCS_getDocumentElement(hDoc,&hRootElm);
if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_getDocumentElement failed"));
XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_terminateEngine();
return ER_ERROR;
}

/* Get the zip code and set it's value to xml document element*/
XRCSStatus = XRCS_getElementsByTagName(hRootElm, _J("zip-code"),
&hElm,&nElmCount);
if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_getElementsByTagName failed"));
XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElement(hRootElm);
XRCS_terminateEngine();
return ER_ERROR;
}

XRCSStatus = XRCS_setElementText(*hElm, lpDS->szZip);


if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_setElementText failed"));
XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElement(hRootElm);
XRCS_freeElementArray(hElm,nElmCount);
XRCS_terminateEngine();
return ER_ERROR;
}

64. Add code and variables to serialize the in-memory XML document to its string
format. Depending on the size of the document both of these representations of the
XML document can be quite memory intensive. Consider ways to minimize the size
of the XML document passed to the business service.

Oracle Proprietary and Confidential 19


Exercise Title <Lesson X.>

JCHAR *newXMLString = NULL;

/* Serialize the XML DOC to XML String */


XRCSStatus = XRCS_serializeDocumentToXMLStringNoEncoding(hDoc,
&newXMLString);
if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_serializeDocumentToXMLStringNoEncoding failed"));
XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElement(hRootElm);
XRCS_freeElementArray(hElm,nElmCount);
XRCS_terminateEngine();
return ER_ERROR;
}

65. Add code and variables to make the call to the business service. Add an if statement
to isolate success return codes from error return codes.

ID idReturnValue = ER_SUCCESS;
JCHAR *bssvPayloadReturn = NULL;

/* call the Business Service */


idReturnValue = jdeCallBusinessService(lpBhvrCom,
lpVoid,
_J("oracle.e1.bssv.J5500050.WeatherForecastProcessor"),
_J("getForecastByZip"),
TRUE,
newXMLString,
&bssvPayloadReturn);

if ( idReturnValue == CallBSSVNoError ||
idReturnValue == CallBSSVNoErrorWithMessages)
{
}
else
{
}

66. Add code to the ‘else’ block to set an error to the application if the call to the
business service did not succeed. Add associated variable and import statement.

#include <b953002.h>

JCHAR *errorText = NULL;


DSDE954000 dsDE954000 = {0};

memset((void *)(&dsDE954000), (int)(_J('\0')),


sizeof(dsDE954000));

errorText = jdeGetBusinessServiceErrorText(idReturnValue);
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__,
0,errorText);
jdeStrncpy(dsDE954000.szWSCallExceptionInfo, errorText ,

20 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

DIM(dsDE954000.szWSCallExceptionInfo));
jdeSetGBRErrorSubText(lpBhvrCom, lpVoid, (ID) 0, _J("007FIS"),
&dsDE954000);

XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElement(hRootElm);
XRCS_freeElementArray(hElm,nElmCount);
XRCS_terminateEngine();
jdeFree(newXMLString);
jdeFreeBSSVPayloadReturn (&bssvPayloadReturn);
return ER_ERROR;

67. Within the ‘if’ block add code to parse the returned XML string, retrieve the root
element and the first level children of that element. Add associated variables.

XRCS_hDocument hBSSVDoc = NULL;


XRCS_hElement *hChildElms = NULL;
unsigned int nChildCount = 0;

XRCSStatus = XRCS_parseXMLStringRemoveEncoding(hParser,
bssvPayloadReturn, &hBSSVDoc);

if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_parseXMLStringRemoveEncoding failed"));
XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElement(hRootElm);
XRCS_freeElementArray(hElm,nElmCount);
XRCS_terminateEngine();
jdeFree(newXMLString);
jdeFreeBSSVPayloadReturn (&bssvPayloadReturn);
return ER_ERROR;
}

XRCSStatus = XRCS_getDocumentElement(hBSSVDoc,&hRootElm);

if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_getDocumentElement failed"));
XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElementArray(hElm,nElmCount);
XRCS_freeDocument(hBSSVDoc);
XRCS_terminateEngine();
jdeFree(newXMLString);
jdeFreeBSSVPayloadReturn (&bssvPayloadReturn);
return ER_ERROR;
}

XRCSStatus = XRCS_getElementChildren(hRootElm,
&hChildElms,
&nChildCount);
if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,

Oracle Proprietary and Confidential 21


Exercise Title <Lesson X.>

_J("XRCS_getElementChildren failed"));
XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElementArray(hElm,nElmCount);
XRCS_freeDocument(hBSSVDoc);
XRCS_freeElement(hRootElm);
XRCS_terminateEngine();
jdeFree(newXMLString);
jdeFreeBSSVPayloadReturn (&bssvPayloadReturn);
return ER_ERROR;
}

68. Add a for loop to iterate through the first level children. Add associated variable.

unsigned int i = 0;

for (i=0; i<nChildCount; i++)


{
}

69. In the “for i” block add code to get the child element’s name and value. Add
associated variables.

JCHAR *elmName = NULL;


JCHAR *elmValue = NULL;

XRCSStatus = XRCS_getElementName(hChildElms[i],&elmName);
if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_getElementName failed"));
XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElementArray(hElm,nElmCount);
XRCS_freeDocument(hBSSVDoc);
XRCS_freeElement(hRootElm);
XRCS_freeElementArray(hChildElms,nChildCount);
XRCS_terminateEngine();
jdeFree(newXMLString);
jdeFreeBSSVPayloadReturn (&bssvPayloadReturn);
return ER_ERROR;
}

XRCSStatus = XRCS_getElementText(hChildElms[i],&elmValue);
if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_getElementText failed"));
XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElementArray(hElm,nElmCount);
XRCS_freeDocument(hBSSVDoc);
XRCS_freeElement(hRootElm);
XRCS_freeElementArray(hChildElms,nChildCount);
XRCS_terminateEngine();

22 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

XRCS_freeString(elmName);
jdeFree(newXMLString);
jdeFreeBSSVPayloadReturn (&bssvPayloadReturn);
return ER_ERROR;
}

70. Still within the “for i" block add code to handle each specific child node. Add
associated variables.

if ( (JCHAR*)NULL != elmValue)
{
if (jdeStricmp(elmName,_J("place-name"))==0)
{
jdeStrncpyTerminate(lpDS->szCity, elmValue,
DIM(lpDS->szCity));
}
else if (jdeStricmp(elmName,_J("state-code"))==0)
{
jdeStrncpyTerminate(lpDS->szState, elmValue,
DIM(lpDS->szState));
}
else if (jdeStricmp(elmName,_J("details"))==0)
{
}
XRCS_freeString(elmName);
XRCS_freeString(elmValue);
elmName = (JCHAR*)NULL;
elmValue = (JCHAR*)NULL;
}

71. Add code to handle the details element (within the “details” else if code block). Since
this is a compound element it will also have to retrieve child nodes much the same
way the root element does. This block of code gets the count of the detail’s child
elements. Add associated variables.

XRCS_hElement *hDetailElms = NULL;


unsigned int nDetailCount = 0;
JCHAR *detailName = NULL;
unsigned int day = 0;

day = day + 1;
XRCSStatus = XRCS_getElementChildren(hChildElms[i],
&hDetailElms,&nDetailCount);
if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_getElementChildren failed"));
XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElementArray(hElm,nElmCount);
XRCS_freeDocument(hBSSVDoc);
XRCS_freeElement(hRootElm);
XRCS_terminateEngine();
jdeFree(newXMLString);
jdeFreeBSSVPayloadReturn (&bssvPayloadReturn);
return ER_ERROR;
}

Oracle Proprietary and Confidential 23


Exercise Title <Lesson X.>

72. Add another for loop (nested within the “for i" loop) to iterate over the detail’s child
elements and process them. Add associated variables.

JCHAR *detailValue = NULL;


unsigned int j = 0;

for (j=0; j<nDetailCount; j++)


{
XRCSStatus = XRCS_getElementName(hDetailElms[j],&detailName);
if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_getElementName failed"));
XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElementArray(hElm,nElmCount);
XRCS_freeDocument(hBSSVDoc);
XRCS_freeElement(hRootElm);
XRCS_freeElementArray(hChildElms,nChildCount);
XRCS_freeElementArray(hDetailElms,nDetailCount);
XRCS_terminateEngine();
jdeFree(newXMLString);
jdeFreeBSSVPayloadReturn (&bssvPayloadReturn);
return ER_ERROR;
}
XRCSStatus = XRCS_getElementText(hDetailElms[j],&detailValue);
if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_getElementText failed"));
XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElementArray(hElm,nElmCount);
XRCS_freeDocument(hBSSVDoc);
XRCS_freeElement(hRootElm);
XRCS_freeElementArray(hChildElms,nChildCount);
XRCS_freeElementArray(hDetailElms,nDetailCount);
XRCS_terminateEngine();
XRCS_freeString(elmName);
jdeFree(newXMLString);
jdeFreeBSSVPayloadReturn (&bssvPayloadReturn);
return ER_ERROR;
}
}

73. Within the “for j” loop add code to determine which detail child element is found an
assign it to the appropriate data structure element. This web service has a fixed
number of detail elements that are returned, so the business function data structure
was created to accommodate all the values. Some web services will have a variable
number of returns and the returned data will have to be stored in a cache prior to
returning it to the application.

if ( (JCHAR*)NULL != detailValue)
{
if (jdeStricmp(detailName,_J("max-temperature-c"))==0)

24 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

{
switch (day)
{
case 0:
jdeStrncpyTerminate(lpDS->szDay1MaxC, detailValue,
DIM(lpDS->szDay1MaxC));
break;
case 1:
jdeStrncpyTerminate(lpDS->szDay2MaxC, detailValue,
DIM(lpDS->szDay2MaxC));
break;
case 2:
jdeStrncpyTerminate(lpDS->szDay3MaxC, detailValue,
DIM(lpDS->szDay3MaxC));
break;
case 3:
jdeStrncpyTerminate(lpDS->szDay4MaxC, detailValue,
DIM(lpDS->szDay4MaxC));
break;
case 4:
jdeStrncpyTerminate(lpDS->szDay5MaxC, detailValue,
DIM(lpDS->szDay5MaxC));
break;
case 5:
jdeStrncpyTerminate(lpDS->szDay6MaxC, detailValue,
DIM(lpDS->szDay6MaxC));
break;
}
}
else if (jdeStricmp(detailName,_J("min-temperature-c"))==0)
{
switch (day)
{
case 0:
jdeStrncpyTerminate(lpDS->szDay1MinC, detailValue,
DIM(lpDS->szDay1MinC));
break;
case 1:
jdeStrncpyTerminate(lpDS->szDay2MinC, detailValue,
DIM(lpDS->szDay2MinC));
break;
case 2:
jdeStrncpyTerminate(lpDS->szDay3MinC, detailValue,
DIM(lpDS->szDay3MinC));
break;
case 3:
jdeStrncpyTerminate(lpDS->szDay4MinC, detailValue,
DIM(lpDS->szDay4MinC));
break;
case 4:
jdeStrncpyTerminate(lpDS->szDay5MinC, detailValue,
DIM(lpDS->szDay5MinC));
break;
case 5:
jdeStrncpyTerminate(lpDS->szDay6MinC, detailValue,
DIM(lpDS->szDay6MinC));
break;
}
}
else if (jdeStricmp(detailName,_J("max-temperature-f"))==0)

Oracle Proprietary and Confidential 25


Exercise Title <Lesson X.>

{
switch (day)
{
case 0:
jdeStrncpyTerminate(lpDS->szDay1MaxF, detailValue,
DIM(lpDS->szDay1MaxF));
break;
case 1:
jdeStrncpyTerminate(lpDS->szDay2MaxF, detailValue,
DIM(lpDS->szDay2MaxF));
break;
case 2:
jdeStrncpyTerminate(lpDS->szDay3MaxF, detailValue,
DIM(lpDS->szDay3MaxF));
break;
case 3:
jdeStrncpyTerminate(lpDS->szDay4MaxF, detailValue,
DIM(lpDS->szDay4MaxF));
break;
case 4:
jdeStrncpyTerminate(lpDS->szDay5MaxF, detailValue,
DIM(lpDS->szDay5MaxF));
break;
case 5:
jdeStrncpyTerminate(lpDS->szDay6MaxF, detailValue,
DIM(lpDS->szDay6MaxF));
break;
}
}
else if (jdeStricmp(detailName,_J("min-temperature-f"))==0)
{
switch (day)
{
case 0:
jdeStrncpyTerminate(lpDS->szDay1MinF, detailValue,
DIM(lpDS->szDay1MinF));
break;
case 1:
jdeStrncpyTerminate(lpDS->szDay2MinF, detailValue,
DIM(lpDS->szDay2MinF));
break;
case 2:
jdeStrncpyTerminate(lpDS->szDay3MinF, detailValue,
DIM(lpDS->szDay3MinF));
break;
case 3:
jdeStrncpyTerminate(lpDS->szDay4MinF, detailValue,
DIM(lpDS->szDay4MinF));
break;
case 4:
jdeStrncpyTerminate(lpDS->szDay5MinF, detailValue,
DIM(lpDS->szDay5MinF));
break;
case 5:
jdeStrncpyTerminate(lpDS->szDay6MinF, detailValue,
DIM(lpDS->szDay6MinF));

26 Oracle Proprietary and Confidential


<Lesson X> Exercise Title

break;
}
}
}

74. After processing of each detail child element the allocated memory needs released.
Within the “if ( (JCHAR*)NULL != detailValue)“ code block add code to
release the memory.

XRCS_freeString(detailName);
XRCS_freeString(detailValue);
detailName = (JCHAR*)NULL;
detailValue = (JCHAR*)NULL;

75. After processing of each root child element the allocated memory needs released.
Within the “if ((JCHAR*)NULL != elmValue)“ code block add code to release
the memory.

XRCS_freeString(elmName);
XRCS_freeString(elmValue);
elmName = (JCHAR*)NULL;
elmValue = (JCHAR*)NULL;

76. Throughout the code the failure cases have cleaned up prior to returning
ER_ERROR. Just before the method returns ER_SUCCESS add code to clean up for
the successful case.

XRCS_freeParser(hParser);
XRCS_freeDocument(hDoc);
XRCS_freeElementArray(hElm,nElmCount);
XRCS_freeDocument(hBSSVDoc);
XRCS_freeElement(hRootElm);
XRCS_freeElementArray(hChildElms,nChildCount);
XRCS_terminateEngine();
jdeFree(newXMLString);
jdeFreeBSSVPayloadReturn (&bssvPayloadReturn);

77. This completes the business function coding. Return to OMW and run Bus Build to
build the business function resolve any compile errors that may occur.

78. From Solution Explorer run the EnterpiseOne Menu option under Tools. Use fast
path to run P5550. This is a test application developed for this exercise. It calls the
business function that was just created when the find button is pressed. Use the
application to retrieve the weather forecast for US zip codes.

Note. The machines used in this exercise are “combination” machines. That is, the
development client, enterprise server, database server, and security server are all hosted
on the same machine. Due to a limitation of this configuration the business function that
was just built is not actually the business function executed. The application is running
the business function on the enterprise server despite the OCM records which would
indicate otherwise. The steps above are correct and will produce a business function that
correctly calls the business service, but this test is actually executing the business
function on the enterprise server which was built and deployed while preparing this
exercise. Standalone installs are also “combination” machines and will behave the same
way. 

Oracle Proprietary and Confidential 27


Exercise Title <Lesson X.>

28 Oracle Proprietary and Confidential

Das könnte Ihnen auch gefallen