Skip to Content
Author's profile photo Jocelyn Dart

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. Why use ABAP OO with Workflow?
  2. Getting started with ABAP OO for Workflow … using the IF_WORKFLOW interface
  3. Using ABAP OO methods in Workflow Tasks
  4. 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 devlopers, 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.

image

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 techncial 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.

image

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.

image

You see below why it is important to use the expression help as the attribute needs to be returned in a specific format.

image

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:

image

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:

image

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.

image

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.

image

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.

image

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.

Assigned Tags

      12 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Ginger Gatling
      Ginger Gatling
      Hi Jocelyn,
      Thanks for this great blog shedding light on using attributes with ABAP OO and workflow.  It's very helpful!

      Best regards
      Ginger

      Author's profile photo Jocelyn Dart
      Jocelyn Dart
      Blog Post Author
      Thanks Ginger. 
      Notice the little tip on narrowing cast? That's also one of the reasons why we don't really need delegation any more... I think after the series I might do a follow-up on related topics like delegation and exceptions.
      Author's profile photo Former Member
      Former Member
      Waiting for your the next blog:)
      Author's profile photo Former Member
      Former Member
      Hi,
      These blogs about workflow are a good starting point for SAP customers who are willing to start using the new tools at hand.

      If I may, here is a suggestion for a future blog: you mentionned delegation and it would be nice to have some sort of comparison between how we used to extend standard BOR objects (by creating subtypes and then setting up a delegation with the super-type) and how it can now be done with standard classes.

      Incidently, delegation made inheritance bottom-up so that we could use the (enhanced) standard BOR objects in custom workflows whereas inheritance seems to be top-down in classes. (Which I take it means that we would use the custom sub-classes in workflows rather than the standard ones when enhancements are needed.)

      Also, it seems that using workflows with custom sub-classes may lead to using several sub-classes (standard and custom) accross one workflow definition to benefit from standard methods, attributes and events as well as custom ones. Wouldn't this happen when the class that one desires to extend does not accept the creation of a custom sub-class (property CREATE PRIVATE set on the class to be extended, for instance) and one has to go up one level in order to be able to create the custom subclass? (If there is such a superclass of course.)

      Well, there are a few other related subjects but I wouldn't want to make this any longer. I am sure that if you are interested in writing about this, you'll come up with additional tips.

      Thanks for the great work,
      Marc

      Author's profile photo Jocelyn Dart
      Jocelyn Dart
      Blog Post Author
      Hi Marc,
      Thanks for the kind comments.

      I'm aware of the delegation issue and it does need to be addressed, and it is a great idea for a future topic. The difficulty at the moment is that given the small but growing amount of standard SAP content in ABAP OO form, the issue of delegation does not seem to have been specifically addressed.  And the classes that have been delivered so far usually have the "Final" flag set, so that you can't create a direct subtype anyway.

      My belief is that although delegation was a convenient way of extending existing business objects, one of the main reasons why this was necessary was the awkwardness of converting from an object type to its subtype and back again.

      With ABAP OO and the new options in the binding editor this awkwardness has disappeared so it is easy to pass a subtype to a task which uses a parent object type and vice versa, which significantly reduces the need for delegation.

      Given that these days it is a matter of moments to create your own task, and quick to create your own workflow or copy of a workflow, and given that customers nearly always copy or significantly change tasks and workflows anyway, the usefulness of the delegation technique in an ABAP OO scenario is minimal. 

      There could also be an argument made that delegation is not really an object-oriented technique and therefore should not be perpetuated into ABAP OO.

      Add to that the many options for directly extending classes in recent releases e.g. via enhancement spots also reduces the need for a formal delegation technique.

      These are just my thoughts and observations on what I have seen so far, and based on discussions with my colleagues.

      Just like virtual and status attributes have had their day, I believe delegation will go the same way.   But even so as a future topic it would be good to explain some techniques for handling scenarios that were previously handled using delegation.

      Hope that helps.
      Regards,
      Jocelyn

      Author's profile photo Former Member
      Former Member
      Hoi Jocelyn,

      I have been using your blogs during my first steps ABAP OO & workflow and find them very usefull, thanks! However I have a question and Im not getting an answer from the Forum, but I am really curious and would be really surprised if my problem could not be solved.

      I want to use attributes in the Long Text of a user decision. (I copied standard task TS00008267 to my own task and want to edit the work item text) but when I want to use an attribute I get message saying:

      'Parameter list missing for method GET_BLABLA'

      Am I doing something wrong? Of have I missed something?

      Hope to hear from you, of maybe you can have a look at my question in the blog?

      Thanks & regards,

      Erik

      Author's profile photo Jocelyn Dart
      Jocelyn Dart
      Blog Post Author
      Hi Erik,
      Glad you are finding the blogs useful! 
      Task TS00008267 is a very special task which makes some special assumptions.  This can sometimes cause strange problems.

      Try your attributes in the long text of a more normal task first - e.g. a send mail step.
      If you get the same error, then the problem is in your attribute or class code.

      If the attribute works ok in a normal task, then there is something particular happening with task TS00008267. 

      Author's profile photo Jocelyn Dart
      Jocelyn Dart
      Blog Post Author
      Hi Erik,
      Glad you are finding the blogs useful! 
      Task TS00008267 is a very special task which makes some special assumptions.  This can sometimes cause strange problems.

      Try your attributes in the long text of a more normal task first - e.g. a send mail step.
      If you get the same error, then the problem is in your attribute or class code.

      If the attribute works ok in a normal task, then there is something interesting happening in task TS00008267.  In which case, check for Notes on http://service.sap.com/notes, and if you don't find a resolution, raise an SAP Message.

      HOWEVER....... remember that Task TS00008267 and any copies of it requires both the workflow step with its Question and Outcomes ***AND*** the task to be complete - so if you are testing your TS task directly instead of via a WS workflow that could be your problem. 

      Hope that helps.
      Regards,
      Jocelyn

      Author's profile photo Former Member
      Former Member
      Hi Jocelyn,

      Thanks for the information shared, am rather referring to it bit late.

      I have created two steps in workflow
      1) Display plant
      2) Decision step

      1st step works ok, but there is error for 2nd step which says
      Method not found: 'CL:ZCL_PLANT.PROCESS'

      Is it because I am using ABAP OO object and object category for Decision step is BOR

      Author's profile photo Former Member
      Former Member
      Hi Jocelyn,

      Please ignore query below
      User decision step worked correctly

      I must have missed something when I was trying it earlier

      Regards,

      Girish

      Author's profile photo Former Member
      Former Member

      Hi Dart,

      How can we define Virtual attribute in ABAP class, can we use Virtual attribute in Work item text in Workflow.

      Author's profile photo Michael Boguth
      Michael Boguth

      Hello Jocelyn,

      first of all, great blogs about workflows. I'm trying to find my way with experimenting in class based workflows and your blogs are very helpful!

      You mentioned in this one

      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).

      I tried with constructor and it works fine. It was new for me that I can put it in here. In codings I saw before it was often like this

            DATA: lr_container TYPE REF TO if_swf_ifs_parameter_container.
      
            lr_container = cl_swf_evt_event=>get_event_container( im_objcateg  = ms_obj_flpor-catid
                                                              im_objtype   = ms_obj_flpor-typeid
                                                              im_event     = 'START_WF' ).
      
            lr_container->set( name  = 'OBJNR'
                               value = md_objnr ).
            lr_container->set( name  = 'PRODUCTID'
                               value = md_productid ).
      
            cl_swf_evt_event=>raise( im_objcateg        = ms_obj_flpor-catid
                                     im_objtype         = ms_obj_flpor-typeid
                                     im_event           = 'START_WF'
                                     im_objkey          = ms_obj_flpor-instid
                                     im_event_container = lr_container ).
      
            COMMIT WORK.
      
      

       

      Maybe you can help me whats the difference between filling variables in constructor and passing them with the set method to the workflow. Is it the same result in both cases?

      Regards
      Michael