Getting Started With ABAP OO for Workflow

February 27, 2017 | Author: SoumyaRanjanPattanaik | Category: N/A
Share Embed Donate


Short Description

Getting Started With ABAP OO for Workflow...

Description

Why use ABAP OO with Workflow? How do I know this is relevant to me? ABAP OO for workflow is available on any SAP NetWeaver platform release 6.20 or above (ABAP stack of course). That includes R/3 4.7, ECC, and the latest versions of SCM, SRM, CRM, xRPM, etc. P.S. There are a couple of minor restrictions in 6.20 that are resolved in 6.40 - but we'll deal with them later in the series. What's the problem with BOR (Business Object Repository)? A little SAP/Workflow history here... SAP Business Workflow came into being in R/3 3.0C. Now for those who can remember back that far, there certainly wasn't any such thing as ABAP OO back then (and it wouldn't be until R/3 4.6C that ABAP OO was available in sufficient depth to support workflow handling). So the Business Object Repository was created as an intermediate, very approximate, but at least object-oriented, solution for SAP Business Workflow. Because it was never intended to be the final solution, there was a limit to how far BOR was going to go. Consequently BOR suffers from:   

   

A very old ABAP editor and relatively feature-poor support tools Awkward and non-obvious macro coding necessitating workflow developers to have special skills above and beyond normal ABAPers or workflow creators Limitations for instantiation, inheritance, generic handling, and calculation of attributes How does ABAP OO solve these problems? Well for starters, ABAP OO is now a fully-fledged object-oriented language with comprehensive feature-rich support tools. ABAP OO also provides: Functional methods for calculation of attributes Proper instantiation and garbage collection Complex inheritance options High reusability for true generic handling of objects What other reasons are there for using ABAP OO with workflow? I've saved the best for last because ABAP OO for workflow means: Any ABAP developer who can code ABAP OO can (after reading this series) code for workflow. So now project managers and workflow creators can call on any ABAP programmer to assist with custom development for workflow - you won't need a specially-trained workflow code-cutter any more. Is there anything I still need to use BOR for? There are a few areas where you might still want to use BOR objects - purely for convenience reasons.



The SELFITEM object for sending mails. This is still useful as everything, including the "Send Mail" step type, is pre-built for you. So it's probably not worth creating an ABAP OO equivalent.





The DECISION object - for user decisions. There's a lot of special functionality around this object for simple question/answer decisions - especially if you are using the UWL. Generic Object Services - a lot of transactions still link to BOR objects - so it can be worth referencing the BOR object to keep the Workflow Overview feature going. BOR events from standard transactions - a lot of transactions that have inbuilt workflow coding that raises BOR events - so it's still handy to reference BOR objects in your ABAP OO classes for these scenarios too. And of course there's a fair bit of business content in provided BOR objects you might want to reuse. Coming Attractions... Over the coming series we'll be discussing

1. 2. 3. 4. 5.

Getting started... using the IF_WORKFLOW interface Using ABAP OO methods in workflow tasks Raising ABAP OO events for workflow Using ABAP OO attributes in workflows and tasks Using functional methods in workflows and tasks



6. Referencing BOR objects in ABAP OO classes So there'll soon be plenty of help to get you going. In the meantime, make sure you get involved in the Business Process Management forum.

Getting started with ABAP OO for Workflow ... using the IF_WORKFLOW interface The basic building block of all ABAP OO for Workflow classes is the IF_WORKFLOW interface. Unless you use the IF_WORKFLOW interface in your classes, the workflow system will not recognize your class as suitable for creating workflow tasks, events, accessing attributes, etc. The class could be a new or existing class. Note: This applies even to utility classes that implement static methods such as calculating deadlines based on factory calendars, de-duplicating a list of agents, or an empty background method for forcing a switch to the workflow system user.

What should I know before reading further? If you've never created an ABAP OO Class before you won't learn how to do that here. So you should have a look at the ABAP Development blogs and tutorials first, or read an ABAP Objects book. Adding the IF_WORKFLOW interface to an ABAP Class Attaching the IF_WORKFLOW interface to an ABAP Class is simple. In the Class Builder (transaction SE24), go to the Interfaces tab and add the IF_WORKFLOW interface. As soon as the interface is added, two sub-interfaces appear: BI_OBJECT and BI_PERSISTENT. Move across to the Methods tab and you will see some methods of these interfaces have been automatically inherited to the ABAP Class. What's the absolute minimum I need to implement from the IF_WORKFLOW interface for a utility class? Open each of the methods inherited from the IF_WORKFLOW interface, and activate the empty source code, then activate the ABAP Class itself. No, really - that's it! What's the absolute minimum I need to implement from the IF_WORKFLOW interface for a class representing a business entity? Open each of the methods inherited from the IF_WORKFLOW interface, and activate the empty source code, then activate the ABAP Class itself. That's the easy bit, the next bit is only fractionally harder, but requires a little explanation. Workflow uses the IF_WORKFLOW interface to generically and efficiently handle all references to ABAP OO for Workflow classes. There is a special part of this interface called the Local Persistent Object Reference, which is simply a way of converting from a generic reference to any object instance used by the workflow system to the specific instance of your ABAP Class and vice versa. The instance is made up of three fields:   

CATID - A two character code indicating the type of object. This is always "CL" for ABAP Classes. I'll explain about other values in a future blog on referencing BOR objects. TYPEID - This holds the technical name of the ABAP Class. INSTID - This is a 32 character field holding the unique instance id. So what do you put in the INSTID field? Unless your ABAP Class is a utility class, usually the ABAP Class would represent a business entity of some kind. In the screenshots in this blog I've shown an example of a class that represents a Plant. To uniquely identify a plant I would use the 4 character Plant number, so for this class the plant number is what I would place in the INSTID field.

Similarly if I had a class representing a Sales Order, I would use the Order number to fill the INSTID field. If I had a class representing a Customer I would use the Customer Number. If I had a class representing a financial document I would concatenate the company code, document number, and fiscal year and use that as the INSTID value. Note: It's a good idea (although not essential) to mark the attribute you use to fill the INSTID value as the "key attribute" in the Class Attributes section. This helps other developers to quickly see which attribute uniquely identifies the instance without having to drill down into method code. What happens if the class represents something that has a unique key longer than 32 characters? In this case you would use a Globally Unique Id (GUID) to represent your unique key, and then relate the GUID back to the real key. A GUID is unique throughout your system - for this reason a lot of the latest SAP solutions use GUIDs rather than meaningful ids as technical ids. To create the GUID, you simply call function module GUID_CREATE. To relate the GUID back to the real key, you could either cross-reference the GUID in a separate custom table, or use an append structure to extend an existing table to also hold a GUID reference. It's convenient to hold the Local Persistent Object Reference value in a public, instance attribute of your class. Workflow won't use the attribute directly, but holding it as an attribute allows you to efficiently fill it once in the Constructor method, and can also be handy for debug and testing purposes. You can call the attribute whatever name you prefer, just make sure you use the data type SIBFLPOR. To be able to reference a unique instance of an ABAP Class in workflow, you need to use the Local Persistent Object Reference in the following two methods inherited from the IF_WORKFLOW interface. BI_PERSISTENT~FIND_BY_LPOR

This is a Static method that is used to convert from the Local Persistent Object Reference used by workflow to a unique instance of the ABAP Class. It's used any time workflow needs to implicitly instantiate the ABAP Class, e.g. when raising an event. Data: lv_plant type werks. move lpor-instid(4) to lv_plant. create object result TYPE ZCL_PLANT exporting plant = lv_plant. BI_PERSISTENT~LPOR

This is an Instance method that converts from the current instance of the ABAP Class to the Local Persistent Object Reference used by workflow. It's used any time the workflow wants to pass a reference to the ABAP Class, e.g. when handling an event. You can either fill in the Local Persistent Object Reference attribute here or preferably (as it is then filled once only per instance) in the Constructor method of the class. * These 3 lines would normally be in the Constructor method me->m_por-CATID = 'CL'. me->m_por-TYPEID = 'ZCL_PLANT'. me->m_por-INSTID = me->plant. 

If the 3 lines above are in the Constructor method, the line below is all you need in the BI_PERSISTENT~LPOR method result = me->m_por. What else can I use the IF_WORKFLOW interface for? The other methods inherited from the IF_WORKFLOW interface are optional, but are useful in certain scenarios. It's up to you to decide whether you want to use them or not. BI_PERSISTENT~REFRESH

This method is used when workflow asks to refresh the object, i.e. reload database and other stored values. You can use it to clear out and re-read existing attributes that were filled in your Constructor and Class Constructor methods, but most of the time it's ok to leave this method empty.

BI_OBJECT~DEFAULT_ATTRIBUTE_VALUE

This method is used in workflow inboxes, such as the Universal Work list, and workflow administration tools to indicate which unique instance of the class is being referenced. By default, whatever value is in the INSTID field of the Local Persistent Object Reference will be shown. If you want to show a different attribute, just add the relevant code. For example, if I have a class representing an instance of a Plant, then the key might be Plant Id, but I want to show the attribute "Description" instead, so I'll add the line: GET REFERENCE OF me->description INTO result. BI_OBJECT~EXECUTE_DEFAULT_METHOD

This method is used in workflow inboxes, such as the Universal Work list, and workflow administration tools, to control what happens when you drill down on the instance of the class being referenced. By default the drill down does nothing. If you want the drill down to call a specific method, typically a display method, then just add the relevant code. For example, if I have a class representing an instance of a Plant, then I might want the default method to be the display method so I'll add the lines: TRY. CALL METHOD me->display. CATCH cx_root. ENDTRY. BI_OBJECT~RELEASE

This method is used by the garbage collector when deleting an instance. You could use it to, for instance, write to a custom log, but most of the time its ok to leave this method empty. Can I call the IF_WORKFLOW methods directly from a workflow task?

Even though the IF_WORKFLOW methods are public methods, they are intended to only be used internally by the workflow engine, and so no, you can't call them directly from workflow (you'll get an error if you even try). So that's what the next blog will be about - how to use an ABAP Class in a workflow task.

Using ABAP OO methods in Workflow Tasks How do I know if I'm ready for this? If you haven't read the first two blogs yet, do that now. 1. Why use ABAP OO with Workflow? 2. Getting started with ABAP OO for Workflow ... using the IF_WORKFLOW interface If you want to try the exercise in this blog in your own system, you will need an ABAP Class with the IF_WORKFLOW interface, and a system/client (SAPNetWeaver 6.20 minimum) with the workflow environment activated. If you aren't sure if your workflow environment is activated, check transaction SWU3 in your system to quickly view and activate the workflow environment in your system. Make sure both the definition and runtime environments are activated, so you can create a task and then test it. As mentioned in the last blog, this blog won't teach you ABAP OO. It won't teach you workflow either, but it should give you enough to get going even if you've never touched workflow before. Note: I've based the examples on an ABAP Class representing a Plant as this is a well-known business entity in most R/3 and ECC systems. However if you are not in a suitable system or just don't want to use a Plant example for whatever reason, you can use your own business entity. All you will need for this exercise is an entity with a key (preferably less than 32 characters in length) and some code to call a display user interface (transaction, function, whatever) for your entity.

How do I use an ABAP OO method in a Task? The simplest type of workflow is a single-step task, i.e. a piece of work that does one thing only. In ABAP OO terms, a single-step task calls one method only to perform this piece of work. In future blogs we'll deal with multi-step workflows, but as multi-step workflows essentially organise single-step tasks, single-step tasks are a good place to start when building workflows. In the last blog I mentioned that you cannot call any method inherited from the IF_WORKFLOW interface directly. So to start we need an additional method in the ABAP Class example we have been creating. The simplest type of method for this purpose is a Public, Instance method with no parameters. A classic example of this is a DISPLAY method. Now of course the code in the method will vary depending on what you are displaying. Here is the code needed to display a Plant in a typical R/3 or ECC system.

method DISPLAY . data: ls_vt001w type v_t001w. CLEAR ls_vT001W. ls_VT001W-MANDT = SY-MANDT. ls_VT001W-WERKS = me->PLANT. CALL FUNCTION 'VIEW_MAINTENANCE_SINGLE_ENTRY' EXPORTING ACTION = 'SHOW' VIEW_NAME = 'V_T001W' CHANGING ENTRY = ls_vT001W. endmethod. Have you noticed that I have used an attribute of the class called PLANT? This is the key (Public, Instance) attribute of my class (data type is WERKS). Make sure you add this attribute to the ABAP Class before you activate your new method. How do you set up the value of Plant? Well of course to create an instance of an ABAP Class in the first place we need a CONSTRUCTOR method, and it's in this method that we fill the attribute plant. Note: Make sure you use the Create Constructor button to add the constructor method to your class. As our ABAP Class represents a business entity, rather than a technical entity, an instance is meaningless without having this key attribute provided. So add an import parameter PLANT (data type WERKS) to the CONSTRUCTOR class so that the plant id can be provided during instantiation. Here is some very simple code for the CONSTRUCTOR method. METHOD constructor . me->plant = plant. ENDMETHOD. Tip! Don't forget to activate and test your class in transaction SE24 before contuining. Now that we can instantiate the ABAP Class and have a method, DISPLAY, that we can call from workflow, we are ready to include the method in a single-step task. To create a single-step task, go to transaction PFTC_INS. Choose the task type "TS" (Standard Task, i.e. a single-step task) and press the Create button. On the second screen the real work begins. On the Basic Data tab, give your task an abbreviation, name, and work item text - these are all free text fields so enter whatever you like. Then choose Object Category "ABAP Class", enter your ABAP Class as the Object Type, and your DISPLAY method as Method. Note: If you are in a 6.20 system and can't see the Object Category choice "ABAP Class", then you first need to execute report SWF_CATID to enable "ABAP Classes" as an available object category. It's already done for you in releases 6.40 and higher. Move across to the Container tab. This is the workflow data storage area - think of it as the equivalent of a data declaration area in a program. You'll notice that workflow has automatically added a container element (equivalent of

a data variable in a program) to hold an instance of your class. It's even marked it as available for import/export from the task to other workflow objects such as multi-step tasks and events. You can drill down on the container element if you want to see more. Save your task, and then there's two things we still need to do before you can test it. 1. You need to clarify how the system will know when this task is complete. For a display task this is easy... running the method is all we have to do, nothing has to be changed on a database or synchronised with another system. So all that's needed is to check the flag Synchronous object method below the Method field on the Basic Data tab, and save the task again. 2. You need to specify who is allowed to execute this task. For simplicity's sake, you can let anyone execute the task by making the task a General Task. Follow the menu path Additional Data - Agent Assignment - Maintain. Place your cursor on the task name, and press the Attributes... button. Select the General Task radio button, press enter and Save your task again. Finally make a note of your task number and go to transaction SWUS to test your task. Type in your task id ("TS" followed by the task number) and press Enter. You'll see the import container elements listed below. You'll need to fill in which plant we want to display. Select the container element _WI_Object_Id and the local persistent object reference to your class is displayed below. Type a valid plant id into the field INSTID, and press Enter. Now simply press the Execute button in the top left hand corner of the screen and you should see the plant details displayed. That's it! How do I explicitly instantiate an instance in a Task? Last time I mentioned that you can't call the special method CONSTRUCTOR directly from a task. Usually that's not a problem for workflow as we would use an event to implicitly create the instance and pass that in as we started the workflow. I'll talk about events in the next blog, but there are occasions when you do want to explicitly create an instance in a workflow step. For example it can be more convenient to instantiate an object based on a flat value attribute of another object, rather than risk potentially recursive code by making the attribute an object instance itself. Or you might simply want to take one of the standard workflow tracked fields, such as the user id that executed a previous workflow step, and get more details, such as the user's name. This is also a good chance to look at:  

Using method parameters with workflow Using background methods with workflow Start by creating a static, public method in your class - call it CREATEINSTANCE. The purpose of this method is to import a plant id and export an instance of the plant class. Make sure you create a suitable signature (import/export parameters) for your method. Inside the class all you need to do is to call the create object command to create the instance. Don't worry about error handling at this stage ... we'll cover that in a later blog. METHOD createinstance. TRY. CREATE OBJECT eo_plantinst EXPORTING plant = iv_plant . CATCH cx_bo_error . ENDTRY. ENDMETHOD. Note: Don't forget to syntax check, activate, and test your method works before using it in workflow. Create a task with your CREATEINSTANCE method just as you did with the DISPLAY method. You'll be asked if you want to "Transfer missing elements from the object method?" - Answer "yes" and you'll notice that the import and export parameters of your method are automatically added to the task container.

This sort of task is a technical step that is called in background by the workflow system, rather than being executed by a user, so instead of making the task a General Task, mark task as a Background processing in the Execution section of the task (below the method on the Basic Data tab). Don't forget to check the flag Synchronous object method and save again as we did for the DISPLAY task. Test your new task using SWUS. Fill the import parameter IV_PLANT with a plant id, e.g. 1000, then press the Execute function. Because the task is executed in background we need to look at the workflow log to see if it worked. Use the Workflow log button display the work item. Then use menu path Extras > Container to see the end result. You should see the container element EO_PLANTINST has an valid reference to the plant class. What about functional methods? Functional methods (i.e. a method with a RETURNING parameter) can be used as above, or you can also use them in workflow bindings (think "parameter passing" between different parts of a multi-step workflow). However at this stage, you only have a single-step task to work with so I'm going to leave how to use functional methods in a binding until later in this blog series by which time I'll have expanded our workflow example a little further. How do I call the task from an application? Although it's possible to call a task directly, e.g. using standard workflow API functions such as SAP_WAPI_START_WORKFLOW, that's not usually the best way to tackle this very common scenario. In general, we call a task by raising an event which then use to trigger the task. So the next blog will be on using ABAP OO events as workflow events.

Raising ABAP OO events for workflow How do I know I'm ready for this? Easy ... did you read the first 3 blogs and create the examples mentioned in blogs 2 and 3? If not, here are the links... 1. Why use ABAP OO with Workflow? 2. Getting started with ABAP OO for Workflow ... using the IF_WORKFLOW interface 3. Using ABAP OO with Workflow Tasks If you want to try the exercise in this blog in your own system, you will need an ABAP Class with the IF_WORKFLOW interface, and a system/client (SAPNetWeaver 6.20 minimum) with the workflow environment activated. You also need to have created the "Display Plant" workflow task mentioned in blog number 3. Note: As mentioned in the last blog, this blog won't teach you ABAP OO. It won't teach you workflow either, but it should give you enough to get going even if you've never touched workflow before. Defining an ABAP OO Event for Workflow Defining an ABAP OO Event for Workflow is the same as defining any other event for ABAP OO. To start just go to transaction SE24, enter your class in edit mode, and go to the Events tab. Give your event a technical name and make sure it is a Public event. Continuing with the ZCL_PLANT class example, here's an example event SITE_VISIT_PROPOSED. You can also define event parameters if you wish by selecting the Parameters button. By definition all event parameters are Exporting parameters, i.e. they are exported with the event when the event is raised. Usually however you don't need to create any event parameters, as the standard Workflow event container (remember that's workflow's name for a data area) adds sufficient standard parameters, such as the user who raised the event, and a local persistent object reference to the ABAP OO class (of course you know all about that because you've read the previous blogs). Of course, you won't see the standard Workflow event container in your class - you'll only see it in the Workflow screens. Here's an event parameter PROPOSED_VISIT_DATE for the event SITE_VISIT_PROPOSED. I've made the parameter Optional so that later we can look at how to raise an event with or without parameters.

Tip! Don't forget to activate your class afterwards.

Using an ABAP OO Event in Workflow For anyone who's using Business Object Events with Workflow, you use ABAP OO Events in exactly the same way. The only real difference is you specify category ABAP Class instead of Business Object. For those who haven't done much with events before, in Workflow an event can be used to:     

Trigger a multi-step workflow Terminate a multi-step workflow Perform special functions on a multi-step workflow, e.g. re-evaluate agents of active work items, cancel and restart with same data Trigger a single workflow task Terminate a single workflow task Note: The last option - terminate a single workflow task - is particularly useful for asynchronous scenarios. For example if you had a task (it could be background or dialog - i.e. involving a user) that kicked off a database update in background, and then let the raising of an event confirm that the change had been committed to the database. If you did this of course you would leave the Synchronous object method flag off in your background task (this flag was mentioned in blog number 3). Triggering a single workflow task with an event isn't a very common practice, simply because most workflows involve more than one step. So usually we want to trigger a multi-step workflow that represents a whole business process. So let's expand our example to a multi-step workflow triggered by an event. Start by calling transaction SWDD, the Workflow Builder. Press the Create New Workflow button - the top-left hand button immediately under the text "Workflow Builder". Then before you go any further, save your new empty workflow. You'll be asked to give it an abbreviation and a name - these are free text and are mainly used when searching for your workflow. Just like our task or an ABAP Class, you'll need to add it to a change request or save it as a Local Object. This going to be a very simple workflow for now, as we are just going to include our "Display Plant" task in it. So to do that, either single-click on the Undefined step in either the Navigation area or double-click on the Undefined step icon in the center Graphical Model editing area. Select the step type Activity and continue on to the next screen. The very first field in the Control tab asks for a task id. Search for your "Display Plant" task by using the search help on the Task field. You can search for all tasks that are based on your ABAP Class. Then just double-click on the appropriate row to bring the task id back into the activity type step Control tab. Now press the key. Workflow will then propose that a reference to your ABAP Class should be added to the Workflow container and automatically creating a binding (mapping) from the reference in the Workflow container to the task container. All you have to do is press the green tick to confirm. All we need to do now is nominate who should perform this step of our business process. To keep it simple for our example, just make the workflow initiator, i.e. the person who started the process, the Agent of the step. In the Agents section, drop down the Expression field to choose the Workflow initiator. Note: Usually we want to calculate who's going to do the work using an agent determination rule but this is just an example after all. Press the green check icon Transfer and to graphic to return to the graphical flowchart view. You can save your workflow again at this point if you wish. We are going to start our workflow with an event and pass in our ZCL_PLANT reference from the event, so we need to allow the new ZCL_PLANT container element to be imported. On the left hand side, under the Navigation area, use the dropdown to swap the bottom left hand area to the Workflow Container display. Double-click on the new ZCL_PLANT container element, and on the Properties tab check the Import flag.

So having completed our mini how-to-create-a-workflow exercise we now want to add the SITE_VISIT_PROPOSED event as the triggering event of the workflow. At the top of the screen press the Basic Data hat icon. On the VersionIndependent tab, choose the sub-tab Start Events. Add a row and enter category CL, then Object Type = your ABAP Class, and then Event of the object = SITE_VISIT_PROPOSED. Tip! It's a good idea to use the dropdown help for all of these fields to avoid typing errors. You can see the event row starts with an A, B, and C columns. B stands for Binding. We need to create the binding (mapping) between the event container and the workflow container to pass across the instance of our ABAP Class and the person who raised the event. Just click on the Binding icon and the binding will be generated for you. Remember the A, B, and C columns? A stands for Activate. Click on the activate icon until the event activation icon turns green. Now use the back arrow icon to return to the graphical flowchart display and use the Activate (lit match) icon at the top of the screen to activate the workflow. Check the status of your workflow is Active, Saved in the Information Area in the top left hand window pane. So now you have a workflow that's linked to a triggering event of your ABAP Class! If you want to test it, use transaction SWUE to generate the event, or just wait until you have completed the next section on raising events. You should see a new "Display Plant" work item added to the Workflow section of your SAP inbox (transaction SBWP). Raising an ABAP OO Event for Workflow Now of course we would not usually raise the event manually, normally an application - a transaction, a BAPI, a function module, a report, a WebDynpro, etc. - would actually trigger the event using code. Raising Business Object events usually involved a traditional function module call - such as SAP_WAPI_CREATE_EVENT. Raising ABAP OO events, not unsurprisingly, uses an object-oriented approach instead of a function module call, a method call is used to raise the event. The provided SAP ABAP Class that handles the raising of workflow events is CL_SWF_EVT_EVENT. This class contains two Static, Public methods for raising ABAP OO events for Workflow:  

RAISE - for raising an event immediately RAISE_IN_UPDATE_TASK - for raising an event in the update task of a Logical Unit of Work Here's some example code to raise our SITE_VISIT_PROPOSED event using the RAISE method - without any parameters. DATA: ls_zcl_plant_key TYPE werks, lv_objtype lv_event lv_objkey

TYPE sibftypeid, TYPE sibfevent, TYPE sibfinstid.

lv_objtype lv_event

= 'ZCL_PLANT'. = 'SITE_VISIT_PROPOSED'.



Set up the LPOR instance id ls_zcl_plant_key-werks = '1000'. MOVE ls_zcl_plant_key TO lv_objkey.



Raise the event TRY. CALL METHOD cl_swf_evt_event=>raise EXPORTING im_objcateg = cl_swf_evt_event=>mc_objcateg_cl im_objtype = lv_objtype im_event = lv_event im_objkey = lv_objkey



IM_EVENT_CONTAINER = . CATCH cx_swf_evt_invalid_objtype . CATCH cx_swf_evt_invalid_event . ENDTRY. COMMIT WORK. Tip! Just as for Business Object events, the COMMIT WORK statement is crucial when raising a Workflow event without this the event will not be raised. Check the event was raised correctly by turning on the event log (using transaction SWELS), and executing the event log. If your event was raised correctly you should have a new line in the event log that looks something like this: The green light icon shows that a workflow was started as a result of this event. The above code is fine for most events that just use the standard Workflow event container and have no specific parameters. Of course if you want to pass specific parameters you need a little extra code to:

1. Instantiate an empty event container 2. Add your event parameter name/value pairs to the event container 3. Raise the event passing the prepared event container Note: You don't need to worry about filling any of the standard event container parameters such as the event creator Workflow will do that as part of raising the event. DATA: ls_zcl_plant_key

TYPE werks,

lv_objtype lv_event lv_objkey

TYPE sibftypeid, TYPE sibfevent, TYPE sibfinstid,

lr_event_parameters lv_param_name

TYPE REF TO if_swf_ifs_parameter_container, TYPE swfdname,

lv_visit_date

TYPE datum.

lv_objtype = 'ZCL_PLANT'. lv_event = 'SITE_VISIT_PROPOSED'. 

Set up the LPOR instance id ls_zcl_plant_key-werks = '1000'. MOVE ls_zcl_plant_key TO lv_objkey.



Instantiate an empty event container CALL METHOD cl_swf_evt_event=>get_event_container EXPORTING im_objcateg = cl_swf_evt_event=>mc_objcateg_cl im_objtype = lv_objtype im_event = lv_event RECEIVING re_reference = lr_event_parameters.



Set up the name/value pair to be added to the container lv_param_name = 'PROPOSED_VISIT_DATE'. lv_visit_date = sy-datum + 7.



Add the name/value pair to the event conainer TRY. CALL METHOD lr_event_parameters->set EXPORTING

  



name = lv_param_name value = lv_visit_date UNIT = IMPORTING RETURNCODE = . CATCH cx_swf_cnt_cont_access_denied . CATCH cx_swf_cnt_elem_access_denied . CATCH cx_swf_cnt_elem_not_found . CATCH cx_swf_cnt_elem_type_conflict . CATCH cx_swf_cnt_unit_type_conflict . CATCH cx_swf_cnt_elem_def_invalid . CATCH cx_swf_cnt_container . ENDTRY. Raise the event passing the prepared event container TRY. CALL METHOD cl_swf_evt_event=>raise EXPORTING im_objcateg = cl_swf_evt_event=>mc_objcateg_cl im_objtype = lv_objtype im_event = lv_event im_objkey = lv_objkey im_event_container = lr_event_parameters. CATCH cx_swf_evt_invalid_objtype . CATCH cx_swf_evt_invalid_event . ENDTRY. COMMIT WORK. If you want to check that your proposed visit date was passed to the workflow, you'll need to create a new workflow container element to hold the proposed visit date, adjust the event to workflow binding, and re-activate your workflow before testing it. What about Configuration options for Workflow Events? Those of you who are familiar with Business Object events in R/3 and ECC are also aware that often no code at all is needed in these systems to raise an event for Workflow - you just need to complete the configuration in one of the many event configuration tables. These tables are provided by many different modules within the application, such as HR, SD message control, status management, and change documents. As of ECC6, most of these configuration tables unfortunately do not yet support ABAP OO events via configuration, with one notable exception - change documents. In transaction SWEC, change document event configuration, you can specify the object category ABAP Class when specifying an event. The only difficulty you may have is matching the key of the change document to the key of your ABAP Class. You can overcome this conversion issue by coding your own conversion routine as a function module. This function module can be called any valid name (within the customer namespace) but must have the same interface as the template function module SWE_CD_TEMPLATE_OBJKEY_FB_2. All you have to do in this function module is use the data in the change document header/items to build the local persistent object reference for your workflow-ready ABAP Class. You then add the function module to the Function module field in the relevant row of transaction SWED - which defines the change document object relationship to an object type. Hopefully some of the other configuration options will catch up soon and allow for ABAP OO event configuration also. Where to now? The next blog will look at fleshing out our workflow by using ABAP OO attributes to add meaningful text, descriptions, and additional parameters to each part of our workflow.

Using ABAP OO attributes in workflows and tasks How do I know I'm ready for this? This is number 5 in a series of blogs on ABAP OO for workflow, so you it would be a really good idea to make sure you have worked through the first 4 blogs. The examples we'll use here continue on from those we used in the earlier blogs. Here's the list of the earlier blogs: 1. 2. 3. 4.

Why use ABAP OO with Workflow? Getting started with ABAP OO for Workflow ... using the IF_WORKFLOW interface Using ABAP OO with Workflow Tasks Raising ABAP OO events for Workflow A little background history for those who know BOR VERY HELPFUL TIP! If you are an ABAP OO programmer and never did any code in the Business Object Repository, skip this section... you don't need to know about it, and you probably don't want to know either. Once upon a time, in the land of BOR (Business Object Repository), there were 3 types of attributes:

1. Database attributes 2. Virtual attributes 3. Status attributes Database attributes were always the easiest of attributes - just say what table and field you want to read and the BOR would generate some code to read all the data from a record of the table. You just had to fill in the blanks. Then you could add other database attributes referring to the same table and they would all use the same pre-generated code. Easy for workflow developers, but not always the most efficient way to read code, as you may only be using one or two fields but you still read the entire table row. Virtual attributes were the most useful type of attribute as you could derive anything here including complex values, structures, tables, and instances of other objects. Status attributes were a neat trick for business objects that used SAP status management, but most programmers didn't even know they existed. By using a special interface, and filling in the code behind a few predefined virtual attributes, you could then generate a yes/no flag to indicate if a particular status of that object was active. In ABAP OO we no longer make the distinctions between these different types of attributes. So what do you lose? No more pre-generated code. And what do you gain? Flexibility and control over how your attributes are coded so that you can make the code as performance-efficient as possible. Tip! Wanting to find whether a status attribute is set or not? Just call function module STATUS_OBJECT_READ with the status object number. All the statuses set for that object will be returned. How do I define ABAP OO attributes for workflow? Simple - just define them on the attributes tab of the ABAP OO Class. You need to specify:   

Attribute id Instance or Static or Constant Data type Don't forget to make the attributes Public so they can be used by workflow. You can also specify a description and an initial value if you wish. In the example below a number of attributes have been added to the ZCL_PLANT class we have been using in the previous blogs to give you an idea. Hint! If you don't want outside programs to be able to change your attribute it's also a good idea to mark it as Read Only. I like to do this for safety's sake.

Can I have attributes that are structures or tables? Of course - the data type of your attribute just needs to be a structure or table type. There's no restriction on the complexity of the structure or table - and in SAP NetWeaver 6.20 and above, being able to handle components of structures and tables in workflow is much easier - especially during binding (parameter passing). Can I have attributes that are objects themselves? Of course - the data type of your attribute just needs to be a TYPE REF TO the appropriate ABAP OO class. You can then refer to attributes of objects that are attributes of another object. While there's no set limit on how many levels down you can go, most workflow developers don't like to delve too deep - because the technical ids become very long and unwieldy. As a general practice if I want to go down further levels, I usually create a workflow container element for the object reference, then use a Container Operation step (a simple assignment step - which behaves something like an ABAP MOVE command) to assign the attribute-which-is-an-object-reference to the container element at runtime. I can then easily refer to attributes of the container element in subsequent steps of the workflow. Can I have attributes that are BOR objects themselves? Of course - but this is a little more involved so it's a separate blog topic for later in this blog series. So where do I put the attribute code? This is very straightforward. As a rule of thumb you put the attribute code of instance attributes in the CONSTRUCTOR method, and the attribute code of static attributes in the CLASS_CONSTRUCTOR method. Like this: METHOD constructor.  

Filling our key attribute from a parameter as we did in the previous blogs me->plant = iv_plant.



Now add some code to supply values to other attributes SELECT SINGLE * FROM T001W INTO me->T001W WHERE WERKS = iv_plant. category = me->T001w-vlfkz. description = me->T001w-name1. CONCATENATE me->plant me->description INTO me->longdesc. ENDMETHOD. If you don't want to use the CONSTRUCTOR or CLASS_CONSTRUCTOR method that's ok. You can always code a separate Public method to derive your attributes, but it does mean you add the overhead of calling that method (as a background task) prior to using the derived attributes in your workflow. I don't personally recommend this approach in 6.40 or above, but in 6.20 it's a way of getting around the lack of functional methods (more on these later). Tip: You can also use private methods as a way of modularizing code within your CONSTRUCTOR or CLASS_CONSTRUCTOR method. Using ABAP OO attributes in tasks For the sake of those of you who don't do a lot of workflow, before you use an attribute of an object, you must first have an object reference in the container (i.e. the data area of your task). Often the object reference is created automatically for you, e.g. an object reference with technical id _WI_Objectid is automatically created when you assign your ABAP OO Class to the task on the Basic Data tab. You can also create your own additional object references in the container quite easily. Go to transaction PFTC_CHG, open your "Display Plant" task from blog 3. Go to the Container tab. Press the Create Element button. Give your

container element a technical name, description, data type, and make sure you mark it as Importing - so that you can pass some data into it later when you test it. You should see something like the example below in your "Display Plant" task from the previous blogs. You can use an attribute in the Work item text on the Basic Data tab. Just position your cursor where you want the attribute to be inserted, press the Insert Variables button just about the work item text, and use the expression help to expand and click on the appropriate attribute. You can see the expression help below. You see below why it is important to use the expression help as the attribute needs to be returned in a specific format. Of course it only makes sense to use simple value attributes here as you only have about 50-70 characters of text that will show as the subject line of your work item in the inbox (depending on which inbox you use). You can also use attributes in the Long text of your work item. Go to the Description tab, make sure Task Description is selected and press the Change Description button. Position your cursor where you want the attribute to go. Use the menu option Insert -> Expression to bring up the expression help. Then just expand the expressions and select the appropriate attribute. The end result should look something like this: Note: If you use complex attributes here you may be asked for more details - such as whether you want each row of a table attribute to appear as a separate line of text at runtime. Now just test your workflow as we did in the previous blogs. In your inbox you should see that the inserted expressions have been replaced by actual values, such as the plant id and description. Using ABAP OO attributes in workflows Just as with tasks, before you use an attribute of an object ion a workflow, you must first have an object reference in the container (i.e. the data area of your workflow). Often the object reference is created automatically for you, e.g. when you added your "Display Plant" task to your workflow a container element was automatically created based on the ABAP OO Class used in the "Display Plant" task. You can also create your own additional object references in the container quite easily. In the bottom left hand pane of the Workflow Builder (transaction SWDD), use the drop down to display the Workflow Container tray. Double-click on the line Double-click to Create. Give your container element a technical name, description, and data type. As we mentioned above, you should already have an appropriate container element in your workflow container that looks something like this: Tip: You only need to mark it as Importing if you are going to pass some data into this element as you start the workflow - if you are just going to use it to hold data between steps of the workflow it doesn't need to be importing or exporting. You can use ABAP OO attributes in any of the control steps in a workflow such as a Container Operation, Loop Until, Multiple Condition, User Decision, etc. Just as with tasks, any time you want to reference an attribute of your ABAP OO Class you simply use the expression help to expand and select the appropriate attribute. To try this out, add a user decision step as the final step in the workflow we created in the previous blog. In the workflow builder flowchart, right-click on the "Workflow Completed" step and you will be presented with a list of step types. Choose the User Decision step type (this is a simple question/answer step). On the Decision page set up the title, outcomes and agents as shown below. Use the drop down help next to Parameter 1to select an appropriate attribute of your plant class. Note: The attribute will replace the &1 placeholder in the title. Transfer the step back to the flowchart by pressing the green tick. Activate your workflow and test it again. Now after viewing your plant you should be presented with a second work item giving the question and answers you created in your decision step and with the plant attribute given a runtime value. How do I pass attributes as parameters and handle narrowing cast? There's one other place where you can use ABAP OO attributes in workflow, Bindings, i.e. the workflow term for parameter passing. Open your workflow again in the workflow builder (transaction SWDD), and drill down on your "Display Plant" task, then press the "Binding (Exists)" button immediately below the Task and Step Name fields. You should see a window appear that looks something like this. In the top panes of the window the workflow and task containers are shown. Down below are the bindings from workflow to task, and from task to workflow (the arrows show you which direction is being used). In the image above you can see I've expanded the plant class and dragged and dropped some attributes of the plant class into the binding. Of course each workflow container element on the workflow side needs to be matched to a task container element on

the task side - so the above binding is not complete. I'm missing is a suitable container element (aka parameter) in the task to pass it to. Which I could easily create in the task as described earlier in this blog. What about if your attribute is a reference to another ABAP OO Class? Can you pass it to a more generic or more specific class reference? Yes of course. Look closely at the binding window again. Between the workflow container element and the task container element it has been assigned to you will see a blue arrow (giving the binding direction) and a button with a filled in arrowhead on it. Press the button and you should see a window like this. If you want to pass an ABAP OO Class reference to a more generic reference (widening cast) you don't have to even look at this window. But if you want to pass an ABAP OO Class reference to a more specific reference (narrowing cast), all you have to do is check the Handle Errors as Warning checkbox and you will pass your class without problem. Of course it's still up to you to make sure the two references are compatible. But what about the performance implications of calculated attributes? I know some of you are well aware that just because you might need an attribute for one particular task or scenario doesn't mean you want to code it in a CONSTRUCTOR method. Particularly if that attribute is resource intensive. So what's the best way to handle this scenario? Functional methods - which of course are the topic of the next blog.

Using functional methods in workflows and tasks How do I know I'm ready for this? This is number 6 in a series of blogs on ABAP OO for workflow, so you it would be a really good idea to make sure you have worked through the first 5 blogs. The examples we'll use here continue on from those we used in the earlier blogs. Here's the list of the earlier blogs: 1. 2. 3. 4. 5.

Why use ABAP OO with Workflow? Getting started with ABAP OO for Workflow ... using the IF_WORKFLOW interface Using ABAP OO with Workflow Tasks Raising ABAP OO events for Workflow Using ABAP OO attributes in Workflows and Tasks What are functional methods? A functional method is a method that returns a single result, i.e. a method that has a Returning parameter. Typically a functional method calculates a value, e.g. you might use a functional method to return the number of entries in a table, or the formatted name of an employee or whatever. The method can have importing parameters, but does not have any other exporting parameters. Here's a simple example using the same ABAP Class we used for the exercises in the previous blogs. This is a static method that retrieves a list of plants relevant for a nominated country. Here are the parameters: And the method code - as you can see it's a very simple example. METHOD plants_of_country. SELECT werks FROM t001w INTO TABLE et_plants WHERE land1 = iv_country. ENDMETHOD. What's the equivalent of functional methods in BOR? For those who are used to coding business objects (BOR) then functional methods replace virtual attributes (a calculation derived from the object instance). Virtual attributes, and their replacement functional methods, are particularly useful where you have a value that can be derived from the current object instance, but there is enough of

a performance cost with deriving the value that you don't want to derive the value every time you construct the instance. One advantage of functional methods over virtual attributes is that you can pass importing parameters. You can derive your calculation from the class instance (assuming you are using an instance method of course) and the importing parameters. However its a fairly simple mechanism so its easy to use this for simple parameters that can be hardcoded into the workflow, but you may still need to call the functional method as the main method of a normal task if you want to dynamically set the parameters. How can I use functional methods in workflows? You can use a functional method in much the same way as an object attribute. For example: in a container operation, or as the source of a binding. Here's an example where a functional method is used in container operation: When selecting your functional method from the drop down look for the "methods" or "functional methods" section within the object. For example this is what the drop down on the Expression field of the Container Operation above looks like: This is the format for passing importing parameters. &ZCL_PLANT.PLANTS_OF_COUNTRY(IV_COUNTRY='DE')& If you have multiple parameters, just separate them with an ampersand (&). Note: You can't use functional methods with importing parameters directly in logical expressions as yet (you can select them but an error is returned) - as the condition editor does not provide a way to enter the parameter values. So in this case, use your functional method in a container operation first, then use the derived container element in your logical expression. How can I use functional methods in tasks? You can use a functional method in much the same way as an object attribute in a task, for example in the subject text of a task or in the binding to a method, with one exception: You can't call a functional method directly from the long text of a task. This is a SAPScript restriction not a workflow restriction - i.e. SAPScript doesn't know how to call a functional method to build the text. However this is not a major problem as you can always create an import container element to hold the result of the functional method in your task, and then in the binding source the container element from your functional method. The example below gives an idea of what such a binding would look like. Can I use a functional method in a task like other methods? Yes of course you can use a functional method as the main method of a task, and then it behaves exactly like any other method called from a task. This could be helpful if you need to handle exceptions for that particular workflow, or if it's simply easier to build that way as for this particular workflow you need to pass many/complex importing parameters. How do I decide whether to use a functional method or create a task? The decision is much the same as for virtual attributes in the BOR repository, i.e.   

Do you need to return more than one value? - If so use a task (of course this task will call a normal method - i.e. one with multiple exporting parameters) Do you need to handle exceptions? - If so use a task Do you only need to return a single value and exceptions are unlikley or irrelevant (will be ignored, or will be checked in a subsequent step)? - If so use a functional method Can I use functional methods for BOR objects? You may notice that functional methods (i.e. methods with the special "result" parameter) can also be selected. However I have personally found them a little unreliable in practice (they tend to throw errors or fail to pass data). A

safer approach would be to link the BOR object to an equivalent ABAP Class, and handle the call to the BOR method inside an ABAP Class method. Linking BOR objects to ABAP Classes is the topic of our next blog.

ABAP Classes in Workflow By Anwesha Bhattacharya , Capgemini India 1.

ABAP Classes and Business Workflow:

We can use ABAP classes in the definition and runtime components of SAP WebFlow Engine in the same way as object types defined in the Business object Repository (BOR). Before proceeding further we need to know where to create and maintain ABAP Classes and ABAP Interfaces. 2.

What is Class Builder and its purpose?

The Class Builder allows us to create and maintain global ABAP classes and interfaces. Both of theseobject types, like global data types, are defined in the ABAP Repository, thus composing a central class library. Together, they form a central class library and are visible throughout the system. We can display existing classes and interfaces in the class library using the Class Browser. We can define local classes as well as global classes. They are defined locally in programs, function groups or as auxiliary classes of global classes of the class pools. Local classes are only visible within the defining module. ABAP classes are processed using the Class Builder. 3.

How to reach Class Builder?

To reach the initial screen of the Class Builder, choose Development Workbench or enter transaction code SE24.

4.

Class Builder from the initial screen of the ABAP

How does it integrate?

The Class Builder allows us to create Web development objects within the ABAP Workbench. We can use the Class Browser to display and maintain existing global object types from the class library. The diagram below illustrates the architecture of the Class Builder and the relationships between its components (including the Class Browser)

From here, we can either display the contents of the class library or edit a class using the Class Editor.Once we have defined an object type, we can implement its methods. From the initial screen or the Class Editor, we can also access the Class Builder‟s test environment. We can define the object types immediately after implementing the method in the ABAP Editor. It is also possible to access the test environment from the initial screen or Class Editor. 5.

How to use the Class Builder?

Use the Class Builder to:            6.

Display an overview (in the Class Browser) of global object types and their relationships. Maintain existing global classes or interfaces. Create new global classes and interfaces. Implement inheritance between global classes. Create compound interfaces. Create and specify the attributes, methods, and events of global classes and interfaces. Define internal types in classes. Implement methods. Redefine methods. Maintain local auxiliary classes. Test classes or interfaces in a simulated runtime environment.

What are the constraints?

We cannot define object types on the basis of graphical object modeling. 7.

Note before creating global classes and interfaces:

Global classes and interfaces that we create in the Class Builder are stored in the class library and administered by the R/3 Repository: they therefore have the same namespace as all other Repository objects. It is therefore necessary to have naming conventions for object types and their components and to use them uniformly within program development.

8.

Naming Conventions in ABAP Objects:

The following naming convention has been conceived for use within the SAP namespace. If we do not observe the naming conventions for object types (classes and interfaces), conflicts will occur when the system creates persistent classes, since it will be unable to generate the necessary co-classes. 9.

Conventions for Object Types:

Class in the class library

CL_

Interfaces in the class library

IF_

Local classes (recommendation) Local interfaces (recommendation)

in

programs LCL_

in

programs LIF_

10. Conventions for Components: Method name



Events



Local type definitions (recommendation)

within

a

class TY_

Data definitions (variables)

Data definitions (recommendation)



(constants) CO_

11. Local Conventions within Methods: For parameters: IMPORTING parameters

IM_

EXPORTING parameters

EX_

CHANGING parameters

CH_

RESULT

RE_

12.

Using ABAP Classes in Workflow:

Within the SAP WebFlow Engine we can use ABAP classes that support the IF_WORKFLOWinterface. Classes that have implemented the IF_WORKFLOW interface are recognized as workflow-enabled in the Class Builder. 13. How to create ABAP Classes that support IF_WORKFLOW interface? 

Go to transaction SE24 and create a customized class.



Next the pop up appears where we need to mention the detail as follows:



Save it and the class is created.



Now the class is to implement IF_WORKFLOW interface. For this go to the tab and declare the IF_WORKFLOW as the interface there and press Enter; two sub-interfaces appear: BI_OBJECT and BI_PERSISTENT. Save the Class.



The

ZCL_TEST

class

now

contains

the

existing

methods

of

IF_WORKFLOW

interface.

14.

Lights on Key Attributes and Attributes: The key attributes are used to define the object key. There can also be other defined attributes other than key attributes. The SAP WebFlow Engine can access all public attributes of a class. Key Attributes:

In the Class Builder there is an additional column Key Attributes on the

tab page as shown below:

We need to check this box when we are defining any attribute as the Key Attribute. All key fields must be character-type fields (elementary types: CHAR, NUMC) and have a defined length. The maximum length allowed for all key fields is 32 characters. The length of the key field for the persistent display is 32 characters. In the case of persistent ABAP objects we can use the GUID, which is generated automatically by the object manager when an instance is created. Attributes: In addition to all the other data types that the Class Builder supports, we can also define attributes with reference to an object from the Business Object Repository (BOR). To do this, we have to use the structure SWOTOBJID as the data type. The BOR object is determined using the corresponding value. To assign a BOR object instance to an attribute we need to use the corresponding BOR macros. Normally, this is implemented within the CONSTRUCTOR of a class.

To use the BOR macros in a class, two INCLUDES must be included.  

Include ……………contains the local types Include ……………contains the BOR macros  An example to show how Attributes:

to

define

Attributes

and

Key

15. Why IF_WORKFLOW Interface? The IF_WORKFLOW interface is necessary when using an ABAP class within the SAP WebFlow Engine. The interface contains methods that allow the object to be used within the SAP WebFlow Engine. The SAP WebFlow Engine handles all objects generically. Objects have to be saved in the event of a context change. Therefore, it is necessary to convert object references in such a way that they can be saved persistently. Conversely, we have to be able to generate the corresponding instance of an ABAP class from the persistently saved key. There are also a number of SAP WebFlow Engine components, for example, the Workflow Log that can display objects. In this case the object has to provide corresponding functions.

The IF_WORKFLOW interface puts a logical parenthesis round the BI_PERSISTENT (instance and BI_OBJECT (object behavior) interfaces. The IF_WORKFLOW interface contains the following methods:

management)

BI_PERSISTENT~FIND_BY_LPOR BI_PERSISTENT~LPOR BI_PERSISTENT~REFRESH BI_OBJECT~DEFAULT_ATTRIBUTE_VALUE BI_OBJECT~EXECUTE_DEFAULT_METHOD BI_OBJECT~RELEASE

A class that implements the IF_WORKFLOW interface can be used in any workflow. The class is automatically released for use in workflows when the interface is implemented. Therefore, we can only make compatible changes to a class after implementation (we cannot delete attributes, change types or delete methods). There is no where-used list to show which workflows the class is used in. Internal classes of an application should not implement the IF_WORKFLOW interface, since this could mean that each method of the class is used in the workflow. Therefore, we should encapsulate the workflow functions in another class that calls the selected methods of the internal class. Each method of the IF_WORKFLOW Interface as mentioned earlier has its distinct functionality, which is discussed below. 16. BI_PERSISTENT~FIND_BY_LPOR Method: If we want to convert a persistent saved display of an object into an instance of the corresponding ABAP class, SAP Webflow Engine calls the BI_PERSISTENT~FIND_BY_LPOR method. Features: The method parameter LPOR is the persistent object reference and is of SIBFLPOR structure type. A reference of BI_PERSISTENT type is returned. The following table shows the components of the SIBFLPOR structure:

Field

Description

CATID

Describes the object type ( CL for ABAP classes)

TYPEID

ABAP class name

INSTID

Object key. The key is limited to 32 characters.

We can implement this method in several ways. In the case of persistent classes we can create the ABAP object instance using the generated classes. In the case of individual persistence management we have to implement the individual actions (such as creating an instance, performing an existence check, entering public attributes, and so on) manually within the class. Instance management takes place automatically in the case of persistent classes. In the case of individual persistence management we also have to carry out instance management by class. The SAP WebFlow Engine does not provide any instance management. We must therefore implement our own instance management in the case of individual persistence management. The FIND_BY_LPOR method should always return the same instance if the following problems are to be avoided: 

Inconsistency in the data display



Instance data being overwritten by another instance Locking conflicts

 There is an implementation example in the CL_SWF_FORMABSENC demo class.

17.

BI_PERSISTENT~LPOR Method: The BI_PERSISTENT~LPOR method is the counterpart to the BI_PERSISTENT~FIND_BY_LPORmethod. It provides the persistent display for an existing instance of an ABAP object. Features: The method returns the persistent display of an object reference as a SIBFLPOR type structure as described earlier. There is a close relationship between the BI_PERSISTENT~FIND_BY_LPOR method and theBI_PERSISTENT~LPOR method. If we call the BI_PERSISTENT~FIND_BY_LPOR method first and then the BI_PERSISTENT~LPOR method, the BI_PERSISTENT~LPOR method must return the same value as was previously used to call the BI_PERSISTENT~FIND_BY_LPOR method. There are also several ways of implementing this method in this case. There is an implementation example in the CL_SWF_FORMABSENC demo class.

18.

BI_PERSISTENT~REFRESH Method: SAP WebFlow Engine calls the BI_PERSISTENT~REFRESH method when the system has to ensure that all values of an object are valid or that they agree exactly with the persistent display of the object. Features: The method implementation depends on the internal organization of the class. We can check the object instance data in the database, if necessary. If we do not need the method in our class, then we need only to carry out a “dummy” implementation (without further coding) to avoid program errors when the system calls the method. There is an implementation example in the CL_SWF_FORMABSENC demo class.

19. BI_OBJECT~DEFAULT_ATTRIBUTE_VALUE Method: The BI_OBJECT~DEFAULT_ATTRIBUTE_VALUE method returns the display name of the object. Features:

We can display references to process objects or process step objects at different positions within the SAP WebFlow Engine (for example, in Business Workplace and in Workflow Log). The object key is normally displayed here. If, for example, we want to display a descriptive text instead, the BI_OBJECT~DEFAULT_ATTRIBUTE_VALUE method has to return the corresponding value. If the method does not contain implementation or does not return a value, the object key is displayed. If we do not need the method in our class, then we need only to carry out a “dummy” implementation (without further coding) to avoid program errors when the system calls the method. There is an implementation example in the CL_SWF_FORMABSENC demo class.

20.

BI_OBJECT~EXECUTE_DEFAULT_METHOD Method: The BI_OBJECT~EXECUTE_DEFAULT_METHOD method is the standard method for the object. This method is executed when, for example, we call the object in Business Workplace. Features: We can display process objects or process step objects at different positions within the SAP WebFlow Engine (for example, in Business Workplace and in Workflow Log). The SAP WebFlow Engine calls the BI_OBJECT~EXECUTE_DEFAULT_METHOD method. If we do not need the method in our class, then we need only to carry out a “dummy” implementation (without further coding) to avoid program errors when the system calls the method. There is an implementation example in the CL_SWF_FORMABSENC demo class.

21.

BI_OBJECT~RELEASE Method: The system indicates that the reference to the instance is no longer needed by using theBI_OBJECT~RELEASE method. This means we can delete the reference from instance management. Once the last reference has been deleted from instance management, theGARBAGE COLLECTOR can release the corresponding memory area. Features: If we do not need the method in our class, then we need only to carry out a “dummy” implementation (without further coding) to avoid program errors when the system calls the method. There is an implementation example in the CL_SWF_FORMABSENC demo class.

22.

How to use ABAP Classes in Process Steps of Business Workflow? In process steps we can use methods and attributes of ABAP classes in the same way as methods and attributes of Business Object Repository (BOR) objects. We can call these methods in the process context. Features: While using the ABAP Classes in the Process Steps the methods may contain dialogs, they can be synchronous or asynchronous; they may appear in the workflow log, and so on.

In general, we can use any method that is implemented as a public method. The method can be implemented in the class itself, in one of the super classes of the class, or by way of an interface. The maximum permitted length for methods that are implemented by way of an interface, for example IF_WORKFLOW~FIND_BY_LPOR, is 30 characters. If the method name is too long, we can choose a shorter name for the method by defining an alias. If the method is implemented in the class or in a super class, the name of the method cannot be longer than 30 characters, so this limitation does not apply. Parameters: We can assign values from the workflow container to the method parameters. Conversely, export parameters can be entered as workflow container values. The following overview shows how the individual types can be used as parameters: Simple types (string, integer, and so on) Data Dictionary types (structures, tables, complex types) References to objects from the Business Object Repository References to ABAP classes (supporting the IF_WORKFLOW interface) We can transfer method parameters that represent a persistent object (IF_WORKFLOW orBOR Object) in the following ways: ABAP classes (with IF_WORKFLOW interface) TYPE SIBFLPORB Object is transferred using the persistent display TYPE REF TO Object is transferred as object reference BOR objects TYPE SIBFLPORB Object is transferred using the persistent display TYPE SWOTOBJID Object is transferred using the persistent display; this display is only valid for BOR objects TYPE SWC_OBJECT Object is transferred as object reference

Exceptions: The SAP WebFlow Engine can deal with exceptions that are triggered by the methods. It differentiates between application exceptions and temporary exceptions. The two exception categories are differentiated by the exception in the class hierarchy or by naming conventions. In the case of a temporary exception, the SAP WebFlow Engine attempts to execute the method again. In the case of a permanent error the status for the workflow is set to error.

Class-Based Exceptions: To create a temporary exception, we can use, for example, the CX_BO_TEMPORARY class or a corresponding subclass. It can be helpful to trigger an exception for dialog methods when the user cancels the dialog. Here, for example, we could trigger the CX_BO_ACTION_CANCELEDexception (subclass of the CX_BO_TEMPORARY class).

Exceptions Not Based on Class: We can also trigger exceptions not based on class. The SAP WebFlow Engine can differentiate between the two exception categories (temporary and permanent) by the name. If the exception begins with TMP or TEMP, it is a temporary exception; otherwise it is a permanent exception.

How to Trigger Class based workflow By Rakesh Dhudipala Scenario: This explains a simple scenario to trigger Class based Workflow from program. Step by Step procedure: Go to SE24 transaction and create a class with ZCL_WEBDYNPRO_WF.

Go to Interfaces tab and implement the interface IF_WORKFLOW

Go events tab and create a event trigger with parameter i_kunnr.

Go to methods tab and and implement the SET_CUTOMER method with I_KUNNR as importing parameter.

Set_customer method write the below code. method set_customer. * Data Declarations DATA: lv_class TYPE sibftypeid, lv_event TYPE sibfevent, lv_objkey TYPE sibfinstid, lr_event_parameters TYPE REF TO if_swf_ifs_parameter_container, lv_param_name TYPE swfdname, lv_id TYPE char10.

lv_class = 'ZCL_WEBDYNPRO_WF'. lv_event = 'TRIGGER'. * Instantiate an empty event container CALL METHOD cl_swf_evt_event=>get_event_container EXPORTING im_objcateg = cl_swf_evt_event=>mc_objcateg_cl im_objtype = lv_class im_event = lv_event RECEIVING re_reference = lr_event_parameters. * Set up the name/value pair to be added to the container lv_param_name = 'I_KUNNR'. " parameter name of the event lv_id = i_kunnr.

TRY. CALL METHOD lr_event_parameters->set EXPORTING name = lv_param_name value = lv_id. CATCH cx_swf_cnt_cont_access_denied . CATCH cx_swf_cnt_elem_access_denied . CATCH cx_swf_cnt_elem_not_found . CATCH cx_swf_cnt_elem_type_conflict .

CATCH cx_swf_cnt_unit_type_conflict . CATCH cx_swf_cnt_elem_def_invalid . CATCH cx_swf_cnt_container . ENDTRY. * Raise the event passing the event container TRY. CALL METHOD cl_swf_evt_event=>raise EXPORTING im_objcateg = cl_swf_evt_event=>mc_objcateg_cl im_objtype = lv_class im_event = lv_event im_objkey = lv_objkey im_event_container = lr_event_parameters. CATCH cx_swf_evt_invalid_objtype . CATCH cx_swf_evt_invalid_event . ENDTRY. COMMIT WORK. endmethod. Go to SWDD transaction and create a new workflow called ZTEST_WF

Go to header and Start events tab and enter the below details

Now if we call the SET_CUSTOMER method it will trigger the ZTEST_WF workflow.

Demo on Workflow using Classes By Richa Gupta, Sparta Consulting Purpose To develop workflow using OOPS concept instead of using standard Business Object. NOTE: Before following this document, one must have a basic knowledge of OOPS Concepts. Steps to follow to use Classes in Workflow How to Create Custom Class Here we will be creating a custom class for MATERIAL. Go to transaction SE24 and create a customized class.

Next the pop up appears where we need to mention the detail as follows:

Save it and the class is created. Now the class is to implement IF_WORKFLOW interface. For this go to the tab and declare the IF_WORKFLOW as the interface there and press Enter; two sub-interfaces appear: BI_OBJECT and BI_PERSISTENT. Save the Class.

The ZCL_TEST class now contains the existing methods of IF_WORKFLOW interface.

Also, 2 new interfaces will be automatically added once you add IF_WORKFLOW interface in the class as shown below:

Each method of the IF_WORKFLOW Interface has its distinct functionality, which is discussed below. BI_PERSISTENT~FIND_BY_LPOR Method:

Here, to create object, constructor of class needs to be implemented as follows:

Here, SET_ATTRIBUTES method is called which will be implemented as follows :

BI_PERSISTENT~LPOR Method:

BI_PERSISTENT~REFRESH Method: If we do not need the method in our class, then we need only to carry out a “dummy” implementation (without further coding) to avoid program errors when the system calls the method.

BI_OBJECT~DEFAULT_ATTRIBUTE_VALUE Method:

BI_OBJECT~EXECUTE_DEFAULT_METHOD Method:

BI_OBJECT~RELEASE Method:

Now, the attributes need to be developed to implement above methods are as follows:

To trigger the workflow using event of class, we must also create an event of the class. To do this, go to EVENTS tab, and there create a new event CREATED as shown below :

Before implementing above methods, a local type needs to be created. To do this, click on LOCAL TYPES as shown below:

Now write the below code:

How to use Class in a Workflow Here, the workflow needs to be triggered as soon as a material is created. And then a workitem should go to initiator to edit the same material. Go to SWDD to create a new workflow. Click on Basic Data Tab :

Give an abbreviation and Short Description to workflow as follows :

Now click on START EVENTS tab and specify the following standard event of the standard class :

Now go back and right click in between the WORKFLOW STARTED and WORKFLOW COMPLETED.

Select CREATE. A list of available step types will be displayed as follows:

Select ACTIVITY from this list. The following screen will appear:

Specify the following details here:

Click on Binding tab. Binding will be as follows:

Click on task description. Automatically following details will show :

Click on the green button for binding above and confirm the bindings must be as follows :

SET AGENT ASSIGNMENT: Click on yellow button coming besides Agent Assignment :

Click on ATTRIBUTES:

Select General Task and click on TRANSFER

How to trigger event of Class To trigger event of a class, we need to call method RAISE of standard class CL_SWF_EVT_EVENT. This method can be called in a user exit, BAdi, or a custom report depending on the requirement. In our case, we are calling the method in a BAdi „BADI_MATERIAL_CHECK‟. The method in which event will be raised is CHECK_DATA.

Create a new custom method RAISE_EVENT in the class implemented for BAdi. Following method will be called to raise event:

Activate class and go back. Now go in CHECK_DATE method and write the below code:

Output Create a new material. To do this, go to MM01.

Press Enter and the following screen will appear :

Specify the above details and press Enter. On the next screen, enter the following details :

Click on SAVE

button.

As soon as the material gets created, the workflow will trigger as shown below in the workflow log :

Introduction Here I am going to explain a simple scenario to trigger Class based Workflow from Web Dynpro ABAP. Scenario: Employee enters his ID and click on a button which triggers Workflow and send mail with Employee ID and Employee Name to Register for the Participation of Event.

I had explained the same scenario in my earlier article How to Trigger Workflow from Web Dynpro ABAP - Part1 , using Business Objects. Now we will see the same using ABAP Classes. In this part, I am focusing on creating ABAP Class and Workflow. Web Dynpro part will come into picture in next part of this article series. After Completion of this Article, You will be able to:



Create ABAP Class to use in Workflow.



Create Workflow.

Creating ABAP Class to use in Workflow Step 1: Create Class. Go to SE24 transaction and Create a Class.

Enter description and click on save.

Here if you want to reuse this class methods in other subclasses, uncheck the check box „Final‟. Go to interfaces tab and enter if_workflow and press enter.

Classes that have implemented the IF_WORKFLOW interface are recognized as workflow-enabled in the Class Builder. As soon as the interface is added, two sub-interfaces appear: BI_OBJECT and BI_PERSISTENT.

Move across to the Methods tab and you will see some methods of these interfaces have been automatically inherited to the ABAP Class.

Step 2: Creating Events. Now go to Events tab and create an event REGISTER as shown below.

Select the event, click on parameters button and create parameter as shown below

Create parameter EMPID as shown below

Step 3: Creating Methods. Go to methods tab, and create method as shown below

Click on parameters button to create parameters for the method register_employee.

Create an importing parameter I_EMPID as shown below.

Create one more method to get employee name.

Select method get_empname and click on parameters button to create parameters.

Create an importing parameter I_EMPID and an exporting parameter E_EMPNAME as shown below.

Step 4: Methods Implementation. Now enter the below code in REGISTER_EMPLOYEE method. REGISTER_EMPLOYEE

method REGISTER_EMPLOYEE. * Data Declarations DATA: lv_objtype TYPE sibftypeid, lv_event TYPE sibfevent, lv_objkey TYPE sibfinstid, lr_event_parameters TYPE REF TO if_swf_ifs_parameter_container, lv_param_name TYPE swfdname, lv_id TYPE char10.

* Setting values of Event Name lv_objtype = 'ZCL_WF_DEMO'. " Your Class Name lv_event = 'REGISTER'. " Event Name. * Instantiate an empty event container CALL METHOD cl_swf_evt_event=>get_event_container EXPORTING

REGISTER_EMPLOYEE

im_objcateg = cl_swf_evt_event=>mc_objcateg_cl im_objtype = lv_objtype im_event = lv_event RECEIVING re_reference = lr_event_parameters. * Set up the name/value pair to be added to the container lv_param_name = 'EMPID'. " parameter name of the event lv_id = i_empid. * Add the name/value pair to the event conainer TRY. CALL METHOD lr_event_parameters->set EXPORTING name = lv_param_name value = lv_id. CATCH cx_swf_cnt_cont_access_denied . CATCH cx_swf_cnt_elem_access_denied . CATCH cx_swf_cnt_elem_not_found . CATCH cx_swf_cnt_elem_type_conflict . CATCH cx_swf_cnt_unit_type_conflict . CATCH cx_swf_cnt_elem_def_invalid . CATCH cx_swf_cnt_container . ENDTRY. * Raise the event passing the prepared event container TRY. CALL METHOD cl_swf_evt_event=>raise EXPORTING im_objcateg = cl_swf_evt_event=>mc_objcateg_cl im_objtype = lv_objtype im_event = lv_event im_objkey = lv_objkey im_event_container = lr_event_parameters. CATCH cx_swf_evt_invalid_objtype . CATCH cx_swf_evt_invalid_event . ENDTRY. COMMIT WORK. endmethod. Just like the function module SAP_WAPI_CREATE_EVENT to trigger business object, we use methodcl_swf_evt_event=>raise in OO to trigger event. Enter the below code in GET_EMPNAME method. GET_EMPNAME

method GET_EMPNAME. * Get employee name corresaponding to employee ID SELECT SINGLE ENAME from pa0001 INTO e_empname WHERE PERNR = i_empid. endmethod.

As we need to implement the interface methods, double click on each of the methods inherited from the IF_WORKFLOW interface, and activate the empty source code. Now save and activate the class.

Creating Workflow Step 1: Creating Workflow. Go to SWDD Transaction and click on Create button to create new Workflow.

Step 1.1: Creating Attributes. Under Navigation Area Work flow container will be selected, If not select Work Flow container as shown below.

Under Workflow Container double click to create as shown below.

Enter Element Name, Description and select the created class.

Under Properties Tab select import, export and click on Ok.

Now Double click again to create emp_id Element which stores the Employee ID. Enter attribute name, description and enter type as shown below. You can enter the data type directly by selecting ABAP dict. Data type.

Under Properties tab check import, export and click on Ok.

Similarly create one more attribute emp_name to store Employee Name.

Under Properties tab check import, export and click on Ok. Click on Save and Save the Work flow.

Step 2: Registering Start Events for Workflow. Click on basic data (hat symbol) as shown below.

Go to Start events Tab and select Category as CL (ABAP Class), Enter Class Name and Enter Event Name (you can select event from F4 help) as shown below.

Step 2.1: Binding Business Object Attributes to Workflow Attributes. Click on binding as shown below

Here binding generated automatically with the matching types, if you don‟t see this binding, bind manually by drag and drop from Class container to Workflow container.

Now you can see empid of Business Object is mapped with emp_id of Workflow Container. Click on OK.

Step 2.2: Activating Start Event for Workflow Click on Activate as shown below.

Once activated it turns to green.

This means once the REGISTERED event of Class ZCL_WF_DEMO is triggered, the Workflow will Start. Click on Save and go back to main screen.

Step 3: Creating Task Double Click on the Undefined Step as shown below.

Select Activity Step and click on Ok.

Click on Create Task as shown below.

Enter abbreviation, Name. Under Object method, select Object category as ABAP Class. Enter Class Name and Method Name (You can select method from F4 help) as shown below. Select the check box 'Synchronous object method'. ( If you don' t select the 'Synchronous' , for Asynchronous method you need to maintain the Terminating Events, In terminating events select the element _WI_OBJECT_ID and select the event name using F4 ) Under Execution Select Background Processing, since no user interaction is required for our scenario.

Click on Save and Click on Back Button. It will prompt to Transfer missing elements. Click on Yes. (You can also click on No and create elements manually).

Click on binding as shown below.

You can see the binding automatically exists with the matching types, since we click on yes in the above step.

Now we can see the Required Mapping. Click on Ok. Now Click on Transfer Button.

Step 4: Creating Send Mail Step Now we can see the Created Task. Click on Create as shown below to create the Mail Step.

Select Send Mail Step and Click on Ok as shown below.

Enter Subject and Click on insert expression to insert Value as shown below.

Select EMP_ID (which holds Employee ID) and click on Ok.

Enter the Body of Mail and click on insert expression under body to insert Value.

Now Click on transfer button.

Enter abbreviation and Name and click on Ok.

Now the Work Flow looks like this.

Triggering Workflow from Web Dynpro ABAP Step 1: Create a Web Dynpro Component. Go to the SE80 transaction and create a web dynpro component.

Click on Yes to create.

Enter Description and click on ok.

Save and Activate the Web Dynpro component. Now double click on MAIN View and go to Context tab of MAIN view. Create node EMPLOYEE with cardinality 1..1 and create an attribute EMP_ID.

Step 2: Layout Design. Now Go to Layout tab: 1.

Create label with text „Employee ID „ and

2.

Create an input field EMP_ID and bind it to EMP_ID of EMPLOYEE node.

3. Create a button with text “Register” and create an Action for the button. 4. Create a Message Area to Display message.

Enter Action Name and description and click on Ok.

Enter below Code in OnActionRegister Event. ONACTIONREGISTER method ONACTIONREGISTER . * Data Declaration for Employee Node DATA lo_nd_employee TYPE REF TO if_wd_context_node. DATA lo_el_employee TYPE REF TO if_wd_context_element. DATA ls_employee TYPE wd_this->Element_employee. DATA lv_emp_id TYPE wd_this->Element_employee-emp_id. * Data Declaration for Class DATA lr_wf_demo TYPE REF TO ZCL_WF_DEMO. * Data Declaration for Message Manager DATA lo_api_controller type ref to if_wd_controller. DATA lo_message_manager

type ref to if_wd_message_manager.

* navigate from to via lead selection lo_nd_employee = wd_context->get_child_node( name = wd_this->wdctx_employee ).

ONACTIONREGISTER * get element via lead selection lo_el_employee = lo_nd_employee->get_element( ). * getting Employee ID lo_el_employee->get_attribute( EXPORTING name = `EMP_ID` IMPORTING value = lv_emp_id ). * Trigger Workflow CREATE OBJECT lr_wf_demo. lr_wf_demo->register_employee( exporting i_empid = lv_emp_id ).

IF sy-subrc = 0. * Get Message Manager lo_api_controller ?= wd_This->Wd_Get_Api( ). CALL METHOD lo_api_controller->GET_MESSAGE_MANAGER RECEIVING MESSAGE_MANAGER = lo_message_manager. * report message CALL METHOD lo_message_manager->REPORT_SUCCESS EXPORTING MESSAGE_TEXT = 'Registered Successfully..'. ENDIF. endmethod. ( Refer How to create and trigger class based workflow - part 1 for quick code reference of class zcl_wf_demo )

Step 3: Create Application. Save and Activate the Web Dynpro Component. Create the Web Dynpro Application and Save it.

Enter description and Click on Ok.

Save the Web Dynpro ABAP Application.

Result Right Click on the Web Dynpro ABAP Application and click on Test.

Enter Employee ID and Click on Register.

Now we can see the success message.

Now go to SBWP Transaction and Click on Inbox.

Conclusion

View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF