Don't change Struct member alignment from 8 bits to 1 bits

advertisement
Develop Web Service Client in JDE OneWorld
By Gan, Li Da | 06 Jul 2010
Background
We knew that E812 and E900 is web-service ready and they are allow to consume web
service via BSSV object. But, how are about other versions of JDE, such as OneWorld? Is it
really that they totally don’t have chance to use any web service up in the magic cloud?
But I changed my opinion after knowing toolkit gSOAP which is an open source C/C++
implementation for web service and client applications.
Technologies
In my solution, the following technologies are involved:
1. JDE APPL
In my sample applications, I am going to develop a simple interactive application
which allows user enter and submit 2 numeric values to web service for the
processing and a numeric result will be returned.
2. C BSFN
JDE APPL is unable to call a 3rd party DLL without going through a BSFN. So a C
BSFN will be developed to dynamically load a custom DLL.
3. gSOAP Web Service (WS) Client (in VC++ DLL)
The main engine behind the whole solution that web-service-enable our JDE
applications. I will use gSOAP toolkit to generate web service proxy/stub files and use
them to develop WS client in VC++ DLL.
4. Java Web Service (published by Oracle OC4J)
To eliminate any network problem, such as firewall blocking, I will setup an Oracle
OC4J within LAN and use it to publish a simple Java Web Service.
Solution
1
User enters values for Number 1 and Number 2, then click button to fire business
function GSOAPBSFN2 which loads a 3rd party DLL vcgsoap2.dll into memory
dynamically and pass in Number 1 and Number 2 to the DLL’s public function.
Through web service proxy using open source gSOAP implementation, vcgsoap2.dll
consumes Java web service Calc1WSSoapHttp published by OCJ4 running on my
other machine. vcgsoap2.dll pass in the value of Number 1 and Number 2 and the
result is returned from web service.
vcgsoap2.dll pass the result back to business function GSOAPBSFN2 which returns
and displays the value at the Result field.
Development
1. Develop and deploy Java WS .
First, download JDeveloper Studio. I am using version 10.1.3.5 which has much
smaller file size than the latest version.
Oracle JDeveloper 11g http://www.oracle.com/technology/software/products/jdev/htdocs/soft11.html
Oracle JDeveloper (10.1.3.5) http://www.oracle.com/technology/software/products/jdev/htdocs/soft10135.html (For
this version, just unzip it to a directory. No installation required.)
Read the tutorial below to learn how to use JDeveloper to create and deploy a Java
web service:
http://www.oracle.com/technology/obe/obe1013jdev/10131/devdepandmanagingws/d
evdepandmanagingws.htm
Create a simple Java Class as following:
2
After create and deploy a web service on the Java class above, you should see a
new web service published under OC4J
Test the web service. Click on Service Description link and rememeber/save the
WSDL address which will be used during gSOAP web service client development.
3
2. Develop JDE BSFN
First, create a DSTR for the new BSFN
Next we create the BSFN itself and attach the new Data Structure to it. Following
general OneWorld procedures generate the skeleton and paste the typedef into the
header.
4
The purpose of this BSFN is to be a pass-through for its DSTR to the VC++ DLL.
Please see the BSFN code on the page 6.
3. Develop JDE APPL
Program the push button to call the new BSFN created above as the following:
5
JDEBFRTN (ID) JDEBFWINAPI GSOAPBSFN2 (LPBHVRCOM lpBhvrCom, LPVOID lpVoid, LPDSD55GSOAPB2 lpDS)
{
/************************************************************************
* Declare structures
************************************************************************/
// Declare function pointer structure. Must use __cdecl calling convention.
typedef void (__cdecl *PFNDLL)(LPBHVRCOM ,LPVOID, LPDSD55GSOAPB2);
/************************************************************************
* Declare pointers
************************************************************************/
HMODULE hLibrary;
PFNDLL lpfndllTemplate;
/************************************************************************
* Check for NULL pointers
************************************************************************/
if ((lpBhvrCom == (LPBHVRCOM) NULL) ||
(lpVoid == (LPVOID) NULL) ||
(lpDS
== (LPDSD55GSOAPB2) NULL))
{
jdeErrorSet (lpBhvrCom, lpVoid, (ID) 0, "4363", (LPVOID) NULL);
return ER_ERROR;
}
/************************************************************************
* Main Processing
************************************************************************/
// Open the dll. If NULL is returned, the DLL could not be opened. vcgsoap2.dll is the DLL we are going to develop later.
if((hLibrary = LoadLibrary(TEXT("vcgsoap2.dll")))==NULL)
return(ER_ERROR);
// Get the memory location of the Entry Point. If NULL is returned, there is no
// such routine in the DLL. dllEntry is the public routine/function exported by vcgsoap2.dll
if ((lpfndllTemplate= (PFNDLL)GetProcAddress(hLibrary,TEXT("dllEntry"))) == NULL)
return(ER_ERROR);
// Call the dll and pass values to DLL
lpfndllTemplate(lpBhvrCom,lpVoid, lpDS);
/************************************************************************
* Function Clean Up
************************************************************************/
FreeLibrary(hLibrary);
return (ER_SUCCESS);
}
6
4. Generate gSOAP web service proxy and XML serialization source code
First, download gSOAP toolkit from http://www.genivia.com/Products/downloads.html
and unzip it to a local directory
Open command prompt and navigate to <gSOAP home dir>\gsoap\bin\win32 and
issue the command below:
wsdl2h -o calc.h <the WSDL address you saved during ws development>
Issue another command:
soapcpp2 –I<gSOAP home directory>\gsoap\import> calc.h
The above command will generate .h and .cpp files for gSOAP web service proxy and
XML serialization routines in source-code format. The files are inside <gSOAP home
dir>\gsoap\bin\win32
7
5. Develop gSOAP web client DLL
- Create new project and configuration
In VC++, create a MFC AppWizard(dll) project and choose Choose Regular DLL with
MFC statically linked. Click Finish.
Open the Settings dialog under the 'Project' drop down menu. Select the 'Link' tab
and locate the Object/library Modules field. And copy and paste the text below right
into the dialog
jdel.lib jdbodbc.lib jdekrnl.lib jdesetup.lib jdeuser.lib jdegbr.lib jdeoblib.lib
jdedia.lib jdedia1.lib jdemail.lib envtool.lib browser.lib jdepkgbld.lib
8
Now go Tools Menu->Options and locate Directories tab. Enter the JDE directories existed on
your computer to 'include' files, 'source' files, and 'libraries' as below:
9
- Include gSOAP’s source files into project
Need to include into project the generated gSOAP source files below:
 soapC.cpp
 soapH.h
 soapClient.cpp
 soapStub.h
 *Soap.nsmap
 Soap*Proxy.h
 stdsoap2.h (This file is in <gSOAP home directory>\gsoap\import>)
 stdsoap2.cpp (This file is in <gSOAP home directory>\gsoap\import>)
10
Again go Project Setting,
set the no precompiler header for the CPP files
included before.
- Edit the main CPP file to call the web service
Now let’s edit the DLL’s main CPP file generated by VC++. For my case, it will be
vcgsoap2.cpp.
Please see the code on page 12 & 13.
11
// vcgsoap2.cpp : Defines the initialization routines for the DLL.
//
#include "stdafx.h"
#include "vcgsoap2.h"
//Include JDE file and BSFN .h file which contain the DSTR data structure passed in
#include <jde.h>
#include <b55gsoap.h>
//Include gSOAP proxy .h file and namespace file generared by gSOAP toolkit
#include "soapCalc1WSSoapHttpProxy.h"
#include "Calc1WSSoapHttp.nsmap"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CVcgsoap2App
BEGIN_MESSAGE_MAP(CVcgsoap2App, CWinApp)
//{{AFX_MSG_MAP(CVcgsoap2App)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CVcgsoap2App construction
CVcgsoap2App::CVcgsoap2App()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CVcgsoap2App object
CVcgsoap2App theApp;
12
//export function dllEntry to public
extern "C" __declspec(dllexport) int dllEntry (LPBHVRCOM lpBhvrCom, LPVOID lpVoid, LPDSD55GSOAPB2 lpDS)
{
//Convert JDE MathNumeric type to long type
long num1, num2, num3;
MathNumericToLong(&lpDS->mnNumber1, &num1);
MathNumericToLong(&lpDS->mnNumber2, &num2);
//Initalize proxy class object
Calc1WSSoapHttp calcws;
//Initialize complex-typed parameters and response objects
ns1__addNumbers *addNumbers;
size_t *addNumbersSize = new size_t;
*addNumbersSize = sizeof(ns1__addNumbers);
addNumbers = (ns1__addNumbers*) soap_instantiate(calcws.soap,SOAP_TYPE_ns1__addNumbers,"","",addNumbersSize);
addNumbers->num1 = num1;
addNumbers->double_USCORE2 = num2;
ns1__addNumbersResponse *addNumbersResponse;
size_t *addNumbersResponseSize = new size_t;
*addNumbersResponseSize = sizeof(ns1__addNumbersResponse);
addNumbersResponse = (ns1__addNumbersResponse*) soap_instantiate(calcws.soap,SOAP_TYPE_ns1__addNumbersResponse,"","",addNumbersResponseSize);
//Call web service method
calcws.__ns1__addNumbers(addNumbers,addNumbersResponse);
//Retrieve return from response object
num3 = addNumbersResponse->return_;
//Convert return value to MathNumeric type
LongToMathNumeric(num3, &lpDS->mnNumber3);
return (TRUE);
}
13
Lastly, compile and build the DLL file.
6. Deployment
Following general OneWorld procedure to deploy JDE APPL and BSFN. After that, copy
the DLL file generated during the previous step into Enterprise Server’s <JDE home
directory>\ddp\B7334\system\bin32 directory.
Now, use it however you wish.
Appendix
To understand the solution further, you are advised to read the following as reference:
1. CurrencyConvertor: How to Use gSOAP and Webservices, Part One by Dr.Luiji
http://www.codeproject.com/KB/webservices/CurrencyConvertor.aspx
2. Custom DLLs http://www.ocode.net/dlls.html by Darren Ricciardi
(Don’t change Struct member alignment from 8 bits to 1 bits and be aware of __stdcall and
__cdecl calling convention if you are developing DLL for Enterprise Server instead of fat client)
3. How to use JDeveloper to create and deploy a Java web service3 by Oracle
http://www.oracle.com/technology/obe/obe1013jdev/10131/devdepandmanagingws/devdepan
dmanagingws.htm
License
This article, along with any associated source code and files, is licensed under The
Code Project Open License (CPOL)
14
Download