Ingres Community Forums Login Register Ingres.com  

Ingres Community Forum


Go Back   Ingres Community Forums > Ingres Forums > OpenROAD Developer's Forum
 

Reply
 
LinkBack Thread Tools Display Modes
Old 2010-02-08   #1 (permalink)
Ingres Community
 
Join Date: Mar 2007
Location: Newcastle, Australia
Posts: 139
Default External class library referencing

Hi,

I'm continuing to investigate the possibility of communicating directly with SAP via its RFC/BAPI mechanism from within OR/Empire. Today I feel like I have come very close .... but there is a problem.

The problem seems to relate to incomplete referencing of external class library components from within Empire. I'll try to explain the situation as well as I can and attach some screen images.

At the moment I'm just trying to put together code to logon to our SAP system. The SAP library which seems to provide this functionality is called 'SAP Logon Control'. I have created an external class library called 'logon' based on this control (Fig_1).

In the 'Class browser' this library shows 5 components (Fig_2). The component containing the attributes and methods of primary interest to me is 'connection'. At least, it contains the attributes and methods which I recognise as working successfully to logon within the VBS and HTA scripting environment.

However, when referencing the external library I've noticed that the class name adopted is 'saplogoncontrol', which happens to be the name of the last item in the list of library components. I'm sure there is a good reason for this naming although I have no idea ....

Anyway, what I'm finding is that I can reference any component attribute or method within my code and compilation goes fine ... BUT ... at runtime ONLY ATTRIBUTES AND METHODS OF COMPONENT 'saplogoncontrol' ARE RECOGNISED! Reference to attributes/methods from any other components result in errors such as that shown in Fig_3. Note that this is the component with the same name as the external library class name. Fig_4 shows that the 'logon' method for class 'connection' does actually exist.

So ... I'm wondering if this behaviour is to be expected? Am I trying to do something stupid? If this is a real problem, is there some way of working around it, say by fiddling with the Empire database repository?

Any advice on this would be really appreciated.

Regards,
Greg Shearer
Attached Images
File Type: jpg Fig_1.jpg (46.2 KB, 8 views)
File Type: jpg Fig_2.jpg (57.9 KB, 8 views)
File Type: jpg Fig_3.jpg (20.0 KB, 8 views)
File Type: jpg Fig_4.jpg (26.6 KB, 8 views)

Last edited by shearerg@onesteel.com; 2010-02-08 at 01:55 PM. Reason: Spelling
shearerg@onesteel.com is offline   Reply With Quote
Old 2010-02-08   #2 (permalink)
Ingres Corp
 
Join Date: Mar 2007
Location: On the OpenROAD
Posts: 723
Default

How did you declare your variables?
Have you tried something like this:
myconn = logon!connection;

You could also try to use a dynamic invocation - sth. like:
methname = varchar(32) not null;
...
methname = 'logon';
myconn.:methname(...);
Bodo is offline   Reply With Quote
Old 2010-02-08   #3 (permalink)
Ingres Community
 
Join Date: Mar 2007
Location: Newcastle, Australia
Posts: 139
Default

Hi Bodo,

And thanks for the reply.
I've tried declaring the variables both as you indicated (my preferred method) and by inserting a 'field from external object' directly onto the form. I hadn't tried dynamic invocation ... but just did and received the same error.

The thing I find most puzzling and annoying is that compilation always proceeds fine, which indicates that the attributes and methods are being checked and found to be correct. For instance, if I change the method name from 'logon' to 'humbug' below, I get a compiler error.

success = myconn.logon(1, True) OK
success = myconn.humbug(1, True) compiler error
%% Error at line 31
E_W40232 The method 'humbug' is not defined for this class.
An attempt was made to invoke the method 'humbug' on an object whose
class does not contain the method 'humbug'. Check the definition of the
class or the spelling of the method name.

However, even with a faultless compilation, at runtime the attributes and methods are not found. I was wondering if being able to change the internal name of the external library class (e.g. from 'saplogoncontrol' to 'connection') could work around the problem, but I can't see any way this can be done.

Thanks again,
Greg
shearerg@onesteel.com is offline   Reply With Quote
Old 2010-02-08   #4 (permalink)
Ingres Community
 
Join Date: Oct 2008
Posts: 18
Default

Haven't seen all you code, but checking the internet and looking at your screenshots, the following should work. Paste this in a new frame in your applicaiton.

Code:
initialize()=
declare
 	oLogon 			= logon!saplogoncontrol;
	oConnection		= logon!connection;
	Logon 			= procedure returning none;
enddeclare
begin
	callproc Logon()
end


procedure Logon =
declare
   iRet = integer not null;
enddeclare
begin
         //can't tell if newconnection is method or property. remove () accordingly
	oConnection = oLogon.NewConnection();
	oConnection.User = 'username';
	oConnection.Password = 'secret';
	//oConnection...further properties
	iRet = oConnection.Logon (CurFrame.WidgetID, FALSE);
	if (iRet = False) then
		CurFrame.Trace('Connection FAILED');
	else
		CurFrame.Trace('Connection SUCCESS');
	endif;
end

Last edited by brogdon99; 2010-02-08 at 10:11 PM.
brogdon99 is offline   Reply With Quote
Old 2010-02-09   #5 (permalink)
Ingres Community
 
Join Date: Mar 2007
Location: Newcastle, Australia
Posts: 139
Default

Brogdon,

Thanks for the reply. It was certainly worth a try .. but unfortunately no luck. Using the 'newconnection' method you suggested brings up the interactive logon interface. The method takes no parameters, and I can't see how to avoid this action. Also, any continuation still produces the error seen previously, indicating that the attributes and methods of oConnection cannot be found.

I'm continuing to look for alternative coding techniques, but nothing working so far.

Thanks again,
Greg
shearerg@onesteel.com is offline   Reply With Quote
Old 2010-02-09   #6 (permalink)
Ingres Corp
 
Join Date: Mar 2007
Location: On the OpenROAD
Posts: 723
Default

Another possibility for the error is:
The method is actually found but produces an error, e.g. because some libraries it requires to run could not be found. Just the error message is misleading.

Could you try to create/insert a field from external class "saplogoncontrol" onto you form, name it oLogon.

Another thing to try:
Use brogdon99's code, but don't call the logon procedure directly in the Initialize block.
Send a userevent to CurFrame instead (could be with some delay), e.g.:
Code:
initialize()=
declare
 	oConnection		= logon!connection DEFAULT NULL;
enddeclare
begin
	CurFrame.SendUserEvent(eventname = 'doLogon', delay=1);
end

ON USEREVENT 'doLogon'=
begin
	oConnection = oLogon.NewConnection();
	oConnection.User = 'username';
	oConnection.Password = 'secret';
	//oConnection...further properties
	iRet = oConnection.Logon (CurFrame.WidgetID, FALSE);
	if (iRet = False) then
		CurFrame.Trace('Connection FAILED,  RfcConnectionStatus='+
                                          varchar(oConnection.IsConnected));
	else
		CurFrame.Trace('Connection SUCCESS');
	endif;
end
Background: Some controls only work correctly if the parent window has been successfully instantiated.
Bodo is offline   Reply With Quote
Old 2010-02-09   #7 (permalink)
Ingres Community
 
Join Date: Oct 2008
Posts: 18
Default

Hi Greg. Here is a version which actually places a control on the frame as Bodo suggested.

Code:
/* Setting properties is supposed to let you log on silently without dialogs */
/*see this -> http://help.sap.com/saphelp_40b/helpdata/pt/39/7e0194ac6011d189c60000e829fbbd/content.htm */
initialize()=
declare
 	oLogon 		= logon!saplogoncontrol;
	oConnection	= logon!connection;
	oExField 	= ExtObjField default null;
enddeclare
begin
	CurFrame.SendUserEvent(eventname = 'LogonSAP', delay = 1);
end

on userevent 'LogonSAP' =
declare
   iRet = integer not null;
enddeclare
begin
    /* make extobjfield */
    oExField = ExtObjField.Create();
    /* parent the field to the frame */
    oExField.ParentField = CurFrame.TopForm;
    /* insert the saplogoncontrol into the extobjfield */
    oExField.Insertobject( extobject = oLogon );
    /* hide the saplogoncontrol field */
    oExField.CurBias = FB_INVISIBLE;
    oConnection = oLogon.NewConnection();
    oConnection.User = 'username';
    oConnection.Password = 'secret';
    //oConnection...further properties
    iRet = oConnection.Logon (CurFrame.WidgetID, FALSE);
    if (iRet = False) then
        CurFrame.Trace('Connection FAILED');
    else
        CurFrame.Trace('Connection SUCCESS');
    endif;
end
Matt
brogdon99 is offline   Reply With Quote
Old 2010-02-09   #8 (permalink)
Ingres Corp
 
Join Date: Mar 2007
Location: On the OpenROAD
Posts: 723
Default

It should be possible to create the activeX control as field on the frame's form directly in the Frame Editor using the "Insert->Field from External Object..." menu item.
You should there be able to select the "SapLogonControl" class, then point and click on your form.
You should also be able to set properties for the external object by selecting the "Object Properties" item within the Property Inspector.
This way you can set properties at design time rather than runtime.
Bodo is offline   Reply With Quote
Old 2010-02-09   #9 (permalink)
Ingres Community
 
Join Date: Mar 2007
Location: Newcastle, Australia
Posts: 139
Default

Bodo and Matt,
I had already tried inserting the control directly into the form ... but the same errors result.

Bodo,
Trying delayed execution via a user event also had no effect.

To me, the big mystery is the fact that all attributes and methods are recognised at compile time but not at runtime. I expect this has something to do with the internal structure/definition of the external library, which is an area in which I have no understanding at all.

As I mentioned earlier, it appears that ONLY attributes and methods which appear under the 'saplogoncontrol' library element are exposed at runtime, whilst all elements are available at compile time.

End result is that I'm not getting any closer to linking directly to SAP on this attempt then on my last .... Anyway, I'll keep thinking about it, and if you have any further ideas please let me know, but I think this may end up in the 'too hard' basket.

Thanks again,
Greg
shearerg@onesteel.com is offline   Reply With Quote
Old 2010-02-10   #10 (permalink)
Ingres Corp
 
Join Date: Mar 2007
Location: On the OpenROAD
Posts: 723
Default

Greg,
could you provide a working example that works on the same machine/environment (where your OpenROAD app runs) using abother language, e.g. VB/VBA/VBS?
As stated before: The problem you see might be a dependency problem.
E.g. you could have the type information for the "connection" class in the registry (this is what the class browser will read), but if there is some problem when instantiating an object of the class at runtime, there is nothing OpenROAD could do about it.
Bodo is offline   Reply With Quote

Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


© 2009 Ingres Corporation. All Rights Reserved