Create consumer BSSV ........
·
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
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.
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
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.
2.
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.
3.
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.
4.
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.
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.
2.
Select Classes
under the EnterpriseOne heading then choose Business Service Class in the right hand pane. Click OK.
3.
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
4.
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){
}
5.
Ctrl-click
on getWeatherByZipCode to see that its signature is:
WeatherForecasts
getWeatherByZipCode(String zipCode) throws java.rmi.RemoteException
6.
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.
7.
Choose General
on the left hand pane and Java class
on the right. Press OK.
8.
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
9.
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.
private String zipCode =
null; // input
private String placeName =
null; // output
private String stateCode =
null; // output
private String status = null; // output
10. 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.
11. Choose
General on the left hand pane and Java class on the right. Press OK.
12. 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
13. 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;
14. Generate
accessors for the WeatherData member variables.
15. Add
an array of type DayForecast to the InternalGetWeatherForecast class.
private DayForecast[] details = null;
16. Generate
accessors for the InternalGetWeatherForecast member variables.
17. 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());
dayForecast[i].setMinTemperatureF(weatherData[i].getMinTemperatureF());
}
internalVO.setDetails(dayForecast);
}
}
18. 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);
19. 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.
3.
On step 2 of 6 uncheck Sign Outbound Messages
4.
On step 3 of 6 uncheck Verify Inbound Signed Request Body
5.
On step 4 of 6 uncheck Encrypt Outbound Messages
6.
7.
On step 5 of 6 uncheck Decrypt Inbound Message Content
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.
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.
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
b. SoftCoding
Key – J5500050
c. Value
– copy the <port-info> element from the generated xml document
14. 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.
15. Launch
the Soft Coding Records application
16. Press
Add
17. Enter
values for these fields
a. User/Role
– JDE
b. Environment
– PD812
c. Template
Name – CUST_J5500050
18. 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.
19. Press
OK
20. 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.
21. Press
Ctrl-Enter and highlight E1SC. Press
Enter.
22. Type
“J5500050” for the soft coding key.
23. Tab
twice and replace BS_NAME with WeatherForecastProcessor
24. Tab
and replace BS_METHOD_NAME with getForecastByZip
25. Tab
twice to exit the code template edit mode.
26. 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;
27. Compile
(context menu > Make) the project
and resolve any compile errors.
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
2.
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
3.
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>
4.
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).
5.
Run or debug the main method until the web service is
called successfully.
6.
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.
7.
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
2.
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
3.
Press OK
4.
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
2.
Press “Design” for the business function then Start Business
Function Design Aid
3.
Take the Form exit to Edit the business function
4.
Within Visual Studio find the declaration for GetWeatherForecast.
5.
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;
}
6.
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);
if(XRCSStatus != XRCS_SUCCESS)
{
jdeVWriteLogEntry(_J("B5500050"), __FILE__, __LINE__, 0,
_J("XRCS_parseXMLString failed"));
XRCS_freeParser(hParser);
XRCS_terminateEngine();
return ER_ERROR;
}
7.
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;
}
8.
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.
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;
}
9.
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
{
}
10. 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 ,
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;
11. 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,
_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;
}
12. Add
a for loop to iterate through the first level children. Add associated
variable.
unsigned int i = 0;
for (i=0; i<nChildCount; i++)
{
}
13. 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();
XRCS_freeString(elmName);
jdeFree(newXMLString);
jdeFreeBSSVPayloadReturn (&bssvPayloadReturn);
return ER_ERROR;
}
14. 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;
}
15. 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;
}
16. 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;
}
}
17. 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)
{
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)
{
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));
break;
}
}
}
18. 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;
19. 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;
20. 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);
21. 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.
22. 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. J
How come I could not google your post? Anyway, thank you for sharing... Sharing is caring...
ReplyDeleteHi, Can you help me? I'm traying create a database value object, but I have this error:
DeleteCan not load Table/View records - [DATABASE_CONNECT_FAILED] Database Connection Failed for for DataSource Object Librarian Local.class com.jdedwards.database.base.JDBException
Are you using jdev 12c? Sometimes we need to initialise E1 workplace ..send detail error on kishorgite048@gmail.com
Delete