‎2007 Jun 08 12:05 PM
As BOR is being phased out is anyone aware of any tools around to convert some useful BOR's to Classes.
I think in general in workflow one should try and use classes and objects wherever possible rather than the older BOR method.
A lot of supplied SAP workflows however are still based on BOR so this area could become a bit of a minefield especially in CRM and similar type of processing.
As new projects come on stream I'd be interested to know how people are going to handle this topic.
Cheers
jimbo
‎2007 Jun 08 12:39 PM
Hello James
If you look at the business object BUS2012 (Purchase Order) its "method" <i>PurchaseOrder.CreateFromData1</i> is realised by BAPI_PO_CREATE1.
This BAPI makes already heavy use of classes, e.g. <b>CL_PO_HEADER_HANDLE_MM</b>. If you look at the methods available for this class it becomes obvious that this class combines lots of functions that are scattered around many function modules.
Since I have little experience with SAP workflow I cannot tell how this will influence workflow development.
However, the OO-conversion of the standard ABAP coding which appears to be almost complete in the SAP_BASIS and SAP_ABA components is progressing towards the business module components.
Thus, it is always worthwile spending some time to search for powerful classes and replace the old-fashioned function modules with them.
Regards
Uwe
‎2007 Jun 08 12:54 PM
Hi,
In order to achieve this openness, SAP provides a technical infrastructure for the R/3 product, the Business Object Repository (BOR), which provides a simple yet powerful mechanism for external systems to trigger core business processes (such as placing an order) without concern for the underlying data structure. This level of abstraction is beneficial because it decouples R/3 from the external system. Either system is therefore free to change its internal business processes without affecting the other. SAP provides this technical infrastructure using a component-based view of its system. Each component or object provides a view of the data and the business processes that interact with that data. External systems can access this data via BAPI methods, which in turn access the underlying data structures of the system. It is the responsibility of the object and the BAPI to ensure the integrity of the data. This encapsulation of the data not only lends itself to external interfaces, but by using objects from within SAP, you can greatly reduce implementation, testing, and maintenance effort via the promotion of code reuse.
Business Objects
A business object is a problem-domain entity that you model in the SAP system, such as SalesOrder, BillingDocument, and Employee. The BOR stores all the objects in the R/3 system. The repository is a group of all the objects in the R/3 system. If the focus of objects is to model atomic business processes then it can be said that the BOR provides an enterprisewide view of business processes. By designing your ABAP code to fit your business processes you increase the ability of that code to flex when those processes are altered or integrated with external systems. This had made the object-oriented approach, which the BOR provides, essential to developing inter-business or e-business functionality.
Attributes
A business object is primarily represented by its attributes. You perform actions, such as create, update, or delete on the attributes by calling the methods of the object.
Attribute NetValue of Object BUS2032 (SalesOrder).
The majority of attributes are data-dictionary fields (for example, the NetValue attribute is defined by VBAK-NETWR). When you access an attribute of an object, you execute a SQL statement that retrieves the corresponding field in the database.
Definition of attribute NetValue.
You can also define attributes that do not exist in the data dictionary. These attributes are called virtual attributes. For example, a business partner has an attribute called BirthDate that is stored in the data dictionary. You can add a virtual attribute to the BusinessPartner object called Age. The age of a business partner is not stored in the database, but you can calculate it using the current date and the birth date of the business partner. If you implement the ABAP code that calculates Age, every time you access the Age attribute, the code executes and returns the business partners age.
Definition of virtual attribute Age.
This is an excellent example of one of the tools that a component-based approach provides. The external system does not need to concern itself with how to gather the data that it requires. The calling program needs only to access the attribute for the data to be returned. This is how business objects decouple the calling program (whether it be in R/3 or external to R/3) from the internals of R/3.
The BOR lets you define multi-line attributes. These attributes define one-to-many relationships between an object and other fields. These objects can be defined in the data dictionary or can also be virtual attributes.
An attribute that uniquely defines an object in the system is called a key attribute. In the case of a SalesOrder, the key attribute is VBAK-VBELN (the TableName and FieldName). It is not uncommon for an object to have several key fields. An example of this is object is the SalesArea (BUS000603) object type which has SalesOrganization (TVTA-VKORG), DistributionChannel (TVTA-VTWEG) and Division (TVTA-SPARTE) as key fields.
Methods
As mentioned earlier, the methods of an object represent the actions you take with objects attributes. An action in this example would include retrieving the status of one or more sales orders based on specific criteria. Methods are analogous to function modules in that they have importing and exporting parameters as well as exceptions, which you view by selecting a method and clicking on the toolbar button. This allows external systems (or internal developments) to pass and accept parameters from these methods just as if they were using function modules -- allowing external systems to call methods.
In Figure 4, the methods shown with the green LED are BAPIs that are called specifically from external systems. They can, however, be called from within the system itself. The method shown with the stop sign is obsolete, but retained for backward compatibility, and should not be used in new developments.
Methods of SalesOrder.
Delegation and Subtyping
One of the most complex concepts in object-oriented development is that of inheritance. This concept lets you extend core functionality by creating a child of the parent object that inherits all of its attributes and methods. For example, a Manager object is a subtype (child) of the Employee object. The Manager object has all the attributes of an Employee object (such as EmployeeID or Name) but also has some extra attributes (such as CompanyCar or ParkingSpace). SAP has not implemented inheritance in the BOR. However, it has provided subtyping and delegation, which offer an alternative way to extend R/3 functionality.
Subtyping
A subtype of an object is another object whose creation is based upon a parent object (see the preceding manager/employee example). The subtype maintains references to all the attributes and methods of its parent object. This means that any methods and attributes defined on the parent can be executed and accessed on the child object. I have often heard less-experienced developers refer to subtyping as copying the parent object. Although the effects can be similar, in order to achieve an understanding of some of the more advanced concepts, such as interface inheritance, it is important to realize that this is not accurate.
If a subtype object were merely a copy of its parent, then all the code contained within the parent would be physically copied to the child. This is not the case. The subtype simply maintains references to its parents methods and attributes. The real difference is that the subtype lets you redefine these methods and attributes. You can easily add your own business rules to the parent methods by redefining the subtypes method. In the following example, I will show why this distinction is so important.
Subtyping Case Study
As an ABAP developer at Acme Tyres Pty. Ltd., you have been given the task of implementing some security measures for the companys online store. The requirement is simple: The password must be at least six characters long.
Modifying SAP code leads to costly and complicated upgrades due to the modified code being overwritten by the newly delivered SAP code. Therefore, The challenge is finding a way of implementing the business logic without modifying SAP code.
After some investigation, you realize that the method CHANGEPASSWORD (in BAPI) on the object KNA1 (Customer) is called when customers change their passwords. All you need to do is create a subtype of KNA1 and then redefine the CHANGEPASSWORD method adding the ABAP code to ensure that the password is a minimum of six characters long. It is of course not wise to change SAP code even assuming you have the passwords, which can be provided only be SAP. After the method is redefined, you just need to implement the business rules in ABAP.
FIGURE 5 Redefinition of ChangePassword method.
It is imperative that once you redefine the method it still behaves in a similar manner. You are allowed to add extra business logic, but the method must still change the password rather than do something unexpected, like delete a customer. This is particularly important when SAP is being accessed from external systems. The external system will expect a method to provide certain functionality. The developer should take care to ensure that this expectation is met.
Delegation
Now that you have implemented a new CHANGEPASSWORD method, you need to tell the SAP system to use the redefined version of CHANGEPASSWORD and not the version that was delivered on the KNA1 object. This is similar to object-oriented inheritance but the two concepts do have fundamental differences.
Delegation for objects.
By making an entry in the delegation table, you tell R/3 that before executing a method on KNA1, it should first check if that method has been redefined on the subtype. If it has, then the system executes the redefined method . If it hasn't, then the system executes the original method. Figure 7 illustrates this process.
Execution flow for methods with delegation.
This delegation is powerful because it lets you implement your own business logic without modifying any SAP code. As long as the objects are properly delegated, your method will be executed.
Responsibility
So far I have shown you two major components of an object, its attributes and methods. The difficulty in SAP is that it has traditionally been a data-driven, procedural-development approach. The BOR is not well understood by developers and managers and thus it is shunned by those that stand to gain the most from it. If managers and developers alike would take a formalized approach to development using business objects, significant savings in the development, testing, and maintenance phases would be achieved. This is due to the high level of re-use that business objects encourage.
Having said this, when a powerful tool is put into the hands of an inexperienced person, chaos can (and usually does) ensue. If object-oriented design principals are not adhered to, then the resulting code has poor reusability and maintainability. Although an in-depth discussion of design issues is beyond the scope of this article, I will introduce in the following section one of the more fundamental design aspects of BOR programming: Responsibility.
When you are given the task of creating a method or attribute on an object, one of the most important questions you should ask is, Does this attribute or method belong on this object? This question is fundamental to an object-oriented design and the answer can make a world of difference. Answering this question incorrectly has detrimental effects on the development effort resulting in methods and attributes strewn across myriad objects, with no coherent structure. If the methods and attributes were strewn across several objects, it would be more difficult to provide a uniform interface to external systems. If an external system wants to execute a particular business process in R/3, it may need to access several business objects, thus increasing coupling and reducing the layer of abstraction between R/3 and the external system.
Lets take, for example, the requirement to be able to update a sales order. This is a common requirement and one that SAP usually implements for you. For the sake of the example, lets assume that SAP has not implemented this method. You will need to implement your own UPDATE method on one of the business objects. The question here is: Which object? This question is what I term as defining responsibility. Which object is responsible for having the UPDATE method on it? As shown in Figure 4, the answer in this cases is BUS2032 (SalesOrder). If you put it on any other object then you run the risk of no one else knowing of its existence. Next time there is a requirement to update a sales order, the developer will develop an additional method. You would then have two separate pieces of code that implement the same functionality. This duplication doubles development, testing, and maintenance requirements. On large projects, this can become a real problem and a maintenance and testing nightmare.
Regards
‎2007 Jun 11 9:28 AM
This doesn't address the topic. All of the above features can be done via OO classes --you can of course have multi-line objects and "virtual attributes" in a class.
A problem with BOR is that you can't easily call these from "Classical ABAP" programming so say you want all the partners of a sales order you normally have to code the functionality yourself using the relevant tables rather than try and get the attributes of a relevant BOR in your program.
However once you've defined say a SALES ORDER class then any ABAP can access the public attributes and methods of this class .
With the BOR it's OK via workflow but a "Normal ABAP" program has to do some fancy coding using the "SWO" or workflow macros and functions to access the attributes of the BOR.
Since these are internal SAP macros and could be deprecated at any time it's really not surprising that outside the Workflow environment BOR's are rarely used in standard ABAP programming.
BOR was a "stepping stone" used by SAP to implement some of the features of OO abap before OO abap became reasonably powerful itself.
Inheritance, encapsulation etc etc are all standard in OO -- not restricted to BOR's.
The trick is to ensure your new class has the functionality of the old BOR and use that wherever possible on new projects.
Like BOR if you extend methods and attributes you don't need to change any existing programs using the relevant classes.
I'm sure the next major upgrade of sap will implement many more business classes -- the old BOR could be retained by simply calling a Class of the same name having the same attributes and objects for legacy code and workflows.
For example here's some ABAP code to call a method which returns the Long Text of a Service notification BOR ZBUS2080 (delagated BOR BUS2080)
You can see it's quite a "Dogs Dinner".
Much more simply and easily done of course if you had a similar CLASS available. (call me=>) etc.
Program ZZREADBOR.
Sample program to execute a method of a business object
or return an attribute of a Business object
can be used in or outside of Workflows etc.
*
Use this as a model
*
Note on some definitions used in WF / Object
programming.
*
A container is a special type of "generalized"
parameter used in workflows for passing data
between steps.
You can use these in "Normal" programming
It's just a generalized structure for holding
data.
An Attribute in this context means a field e.g Short
text. The attribute can be a table (multi-lined)
as well.
The attribut is defined in the attribute list
of the business object
Use transaction SWO1 to see the list.
Operations on containers are done via
standard SAP Workflow macros
swc_function such as swc_create_object.
You must supply a key to instantiate the object
and the object name
(Instantiation means just supplying
the objects key --such as
in the case of a sales order the key would be
the sales order number).
Parameters
Enter Business object name e.g ZBUS2080
key of business object e.g sales doc nr etc.
Attribute you want if getting an attribute property
Method name if executing a method.
For retrieving attributes the data is returned
in field return.
For Methods a little extra work is required as follows:
For Methods you may need extra container
parameters such as
tables (swc_get_tabe container containerElement Itab)
*
To see what elements are needed have a look at the
Method code (transaction SWO1=== select
the business object(display) chose the method and then
select the program button
container parameters will be identified the code
by swc_set_element / table for export parameteres
swc_get_element / table for import parameters.
ensure you set your container(s) to persistent
this ensures the container exists throughout
the whole run and is available to sub programs
function modules, methods etc.
if you don't do this then the container only exists
in the program and disappears when you enter a function
module method etc etc.
Jim Hawthorne Nov 2005.
*
include <cntn01>. "SWC macros and WF container stuff
tables: tojtb, swotdv. "Bus Obj <====> program
Sample demo executes method getdetail
which retrieves long text etc from bus object ZBUS2080.
parameters: p_bus like tojtb-name default 'ZBUS2080',
p_key like swotobjid-objkey default '000300000153',
p_attrib like SWOTRA-ATTRIBUTE,
p_method(32) default 'GETDETAIL'.
constants: c_attrib value 'A',
c_method value 'M'.
data: BEGIN OF RETURN.
INCLUDE STRUCTURE SWOTRETURN.
DATA END OF RETURN.
data: BAPIRETURN LIKE BAPIRETURN.
data: l_invoke LIKE swotinvoke.
data: w_prog like tojtb-progname,
w_runname like tojtb-progname,
w_super like tojtb-parent,
w_type(1) type c.
swc_container container.
swc_container_to_persistent container.
data: object like swotrtime-object.
data: w_object like swotobjid.
if p_method = ' '.
w_type = c_method.
else.
w_type = c_method.
endif.
break-point 1. .
w_object-objkey = p_key.
w_object-objtype = p_bus.
get actual program name where method / attribute
exists.
If verb is not in the object type
then use the supertype.
select single progname parent into (w_prog, w_super)
from tojtb
where name eq p_bus.
select single * from swotdv
where objtype = p_bus
and verb = w_type.
case sy-subrc.
when 0.
w_runname = w_prog.
when 4.
select single progname parent into (w_prog, w_super)
from tojtb
where name eq w_super.
w_runname = w_prog.
endcase.
case p_method.
when ' '.
Method not entered so attribute required.
CALL FUNCTION 'SWO_PROPERTY_GET'
EXPORTING
OBJECT = w_object
ATTRIBUTE = p_attrib
CHANGING
VALUE = return.
EXCEPTIONS
ERROR_CREATE = 1
ERROR_INVOKE = 2
ERROR_CONTAINER = 3
OTHERS = 4
IF SY-SUBRC <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
when others.
Method required.
1 ) Must instantiate the object first.
CALL FUNCTION 'SWO_CREATE'
EXPORTING
OBJTYPE = p_bus
OBJKEY = p_key
IMPORTING
OBJECT = object
RETURN = return.
IF SY-SUBRC <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
Execute the method.
*
*
for swo invoke -- access type 'G' ====> get attribute
access type 'C' ====> execute a method
this function is executed internally.
in the perform (p_method) statement the sap kernel knows
that the program is actually a business object type of program
not a "Normal" abap so the perform gets handled a little
differently than the usual perform statement.
You cannot execute the BOR program via SE38.
set any input and output parameters
for your method.
*
You will have to code them here
swc_set_element container 'User' p_key.
l_invoke-object = object.
l_invoke-lobjtype = p_method.
l_invoke-verb = p_method.
l_invoke-objkey = p_key.
l_invoke-reftype = 'D'.
l_invoke-synchron = 'X'.
read comments above again to understand the difference
in how this statement works compared
to a normal perfom xxxx in program yyyy.
*
if you have more parameters such as container tables then add them
to the tables statement.
for example to get long text and other info from business object
ZBUS2080 (Service Notification)
data:
notifheader like bapi2080_nothdre,
notifhdtext like bapi2080_nothdtxte,
notlongtext like bapi2080_notfulltxte occurs 0,
notitem like bapi2080_notiteme occurs 0,
notifcaus like bapi2080_notcause occurs 0,
notifactv like bapi2080_notactve occurs 0,
notiftask like bapi2080_nottaske occurs 0,
notifpartnr like bapi2080_notpartnre occurs 0,
return2 like bapiret2 occurs 0.
swc_set_table container 'NotLongText' notlongtext.
swc_set_table container 'NotItem' notitem.
swc_set_table container 'NotifCaus' notifcaus.
swc_set_table container 'NotifActv' notifactv.
swc_set_table container 'NotifTask' notiftask.
swc_set_table container 'NotifPartnr' notifpartnr.
swc_set_table container 'Return2' return2.
perform (p_method) in program (w_runname) tables container
changing
l_invoke.
now retrieve your data back from the method.
if you have extra parameters add extra swc_get statements.
break-point 1.
swc_get_table container 'NotLongText' notlongtext.
swc_get_table container 'NotItem' notitem.
swc_get_table container 'NotifCaus' notifcaus.
swc_get_table container 'NotifActv' notifactv.
swc_get_table container 'NotifTask' notiftask.
swc_get_table container 'NotifPartnr' notifpartnr.
swc_get_table container 'Return' return2.
field-symbols: <g>.
loop at notlongtext assigning <g>.
write: / <g>.
endloop.
endcase.
break-point 3.
write: / 'done'.
.
Cheers
Jimbo
‎2008 Jul 07 6:46 AM
There's a blog in using OO and classes instead of BOR.
Some older modules like some parts of SD and almost the whole of FI were written "Donkeys years ago" so I expect these to be one of the last to be changed.
With newer technology sych as SOAP and BPM the old "Classical Workflow" idea itself is becoming outdated anyway since this will be generated automatically in Business Process modelling -- becoming more and more important.
Cheers
-Jimbo