Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

Using pseudo-comments to emulate annotations in ABAP

Former Member
0 Kudos

We are porting GUICE library (http://code.google.com/p/google-guice/) from Java to ABAP. For full support we need annotations in ABAP (just like they are in Java). We figured out that we can do this pretty easily by using pseudo-comments in ABAP.

Here's an example. We have the following public section for a class (available by Goto->Public Section when editing a class in transaction SE80).

class ZDZ_ACLASS definition
  public
  final
  create public .
  "#@MyAnnotation

*"* public components of class ZDZ_ACLASS
*"* do not include other source files here!!!
public section.

  data PUB_ATT1 type INT4 .

  methods PUB_METHOD1
    importing
      !IA type INT4 .
  methods PUB_METHOD2
    importing
      !IA type INT4
      !IB type INT4
      !IC type INT4
      !ID type INT4 .
  class-methods STATIC_PUB_METHOD1 .

You probably noticed the pseudo-comment "#@MyAnnotation added just after class definition. It's added just as ABAP Unit #AU comments. We can process this annotation pretty easy by using the following code.

DATA:
        compiler TYPE REF TO cl_abap_compiler
        , p_name TYPE program
        , p_include TYPE program
        , p_result TYPE scr_glrefs
        , result_line TYPE scr_glref
        , error TYPE c
        , errors TYPE scr_errors
        , abort TYPE c
        , comments TYPE scr_comments
        , comment TYPE string
        , p_includes type SCR_PROGRAMS
        .

  append 'ZDZ_ACLASS====================CU' to p_includes.
  append 'ZDZ_ACLASS====================CO' to p_includes.
  append 'ZDZ_ACLASS====================CI' to p_includes.
  p_name = 'ZDZ_ACLASS====================CP'.


  CREATE OBJECT compiler
    EXPORTING
      p_name    = p_name
      p_includes = p_includes.

  CALL METHOD compiler->get_all_refs
    EXPORTING
      p_local       = ' '
*    p_testcode    = ' '
*    p_types       =
*    p_grades      =
*    p_no_includes =
*    p_extended    =
*    p_internal    =
    IMPORTING
      p_result      = p_result
      p_error       = error
      p_errors      = errors
      p_abort       = abort
      .

  LOOP AT p_result INTO result_line.
    WRITE: / ' ', result_line-tag, space , result_line-full_name.
    LOOP AT result_line-symbol->pseudo_comments INTO comment.
      WRITE: / '    ', comment.
    ENDLOOP.
  ENDLOOP.

The problem is with the fact that if we now edit public seciton of a class not by using 'Goto->Public Seciton', but by using the old table-style editor, then our custom pseudo-comments are thrown away.

We tested it on a system where SAP_ABA is Release 701 Level 0005. I've also checked that with the introduction of EHP2 (http://www.sdn.sap.com/irj/sdn/index?rid=/webcontent/uuid/1009fbb7-fd08-2d10-0182-852b6fa05f08&prtmode=print [original link is broken]) we will have a new editor that will not be table based (however, I don't have access to a system running EHP2).

My questions are:

- is there anyone running EHP2 that can check for me if any comment added to the public section of a class manually (Goto->Public Seciton) gets overridden, when you modify public section of a class by using the table-style editor

- is there anyone working closely to SAP ABAP development that can tell me why this behavior in editor is occuring - is it a bug, or a feature

- anyone can think of a workaround/fix - the obvious one that I can imagine is say to every programmer: don't use table-based editor - always modify public section by 'Goto->Public Section' - which is of course unreasonable

Edited by: Rob Burbank on Nov 26, 2010 10:05 AM

1 ACCEPTED SOLUTION

former_member183804
Active Contributor
0 Kudos

Hello Dominik,

using pseudo comments for global classes is doomed, there is no chance since the form based class builder creates the source of the public, protected, private section and the METHOD statement out of Meta Data. The mentioned reference ABAP Unit also has got a hard coded hook into the meta data of the class builder.

Possibly classification can solve the problem with global classes while psuedo comments are used for local classes.

http://aiokeh.wdf.sap.corp:1080/SAPIKS2/contentShow.sap?TMP_IWB_TASK=DISPLAY&_CLASS=IWB_EXTHLP&_LOIO...

Hopes this helps

Klaus

23 REPLIES 23

former_member183804
Active Contributor
0 Kudos

Hello Dominik,

using pseudo comments for global classes is doomed, there is no chance since the form based class builder creates the source of the public, protected, private section and the METHOD statement out of Meta Data. The mentioned reference ABAP Unit also has got a hard coded hook into the meta data of the class builder.

Possibly classification can solve the problem with global classes while psuedo comments are used for local classes.

http://aiokeh.wdf.sap.corp:1080/SAPIKS2/contentShow.sap?TMP_IWB_TASK=DISPLAY&_CLASS=IWB_EXTHLP&_LOIO...

Hopes this helps

Klaus

0 Kudos

Thanks for your answer. This shades a little bit of light on the future (or its lack) of our implementation.

Looks like the link you provided is internal to your company. Can you provide some link that is working from the internet, or copy-paste the text you're referring to?

If not, is there a possibility that you send it to me via email: dominikz(at)genijusz.com?

0 Kudos

Hi Klaus,

actually I have some more thoughts about your comment.

- You're saying that from table editor public/protected/private section is generated and overriden. I'm not saying it's untrue because probably that is the case. However

  • afaik from 7.0 you can edit public/protected/private section and your changes are stored in REPOSRC table directly as source code

  • if you make such a change and never touch table-style editor, the class works well (even with comments added)

So do you think it would be possible to fairly easy release a SAP note with code corrections that would merge table changes into REPOSRC headers?

The way I would do it is by using cl_abap_compiler that already parses and stores comments in PSEUDO_COMMENT table. Probably this is the way you populate table editor with data. So the only thing to do is store PSEUDO_COMMENTs tables somewhere and use them when re-generating public/protected/private headers.

I know it may sound like an easy task from my side but probably when it comes to SAP there are much more issues to solve. I'm just wondering how hard that change would be.

- If we cannot get in reasonable time the above change (and EHP2 coming soon will also not solve the problem), then is there any user exit that we can use to plug into public/protected/private header generating code so that we can hook our pseudo-comments code the same way as ABAP Unit does?

- If both of above are not possible, is there a way to put a button into SE80 with our custom code? Then we would store pseudo comments somewhere else, but the user could click the button called Store/Restore that would either

  • get the pseudo-comments out of source code and store them in our custom table

  • put the pseudo-comments back from custom tables to the source code

I'm already grateful for your previous answer. If this is too much answers I'm asking for, don't hesitate to let me know.

0 Kudos

Pseudo-comments for the ABAP Unit is being generated from the fields Runtime Limit and Limit of Risk Level on the Properties tab. If we change it on properties, it would change the actual pseudo-comments on the Public section and vice versa. My point here is, these properties are stored in the DB (SEOCLASSDF-RISK_LEVEL) which generates this pseudo-comments. So, you need to have something in SE24 or Custom Transaction to store these type of attributes and create them as pseudo-comments.

Regards,

Naimesh Patel

0 Kudos

Hello Dominik,

you are welcome. I will try to answer your question as far as I know. I know a bit or too, but well I am no expert on the ways of the source code editors.

> You're saying that from table editor public/protected/private section is generated and overriden. ...

Well maybe I should rephrase that a little bit. The form based class builder synchronizes its meta data with the source code. Whenever one performs a refactoring in the form based class builder it is possible that the class builder recreates source code out of its meta data. Elements not part of the meta data, e.g. pseudo comment get lost by such a procedure.

> The way I would do it is by using cl_abap_compiler that already .. I'm just wondering how hard that change would be.

To store the pseudo comments in the meta data would require the repository to get changed. I would be surprised uf such a change would be done as patch for shipped releases. It would not bet fortune that this will become true.

- .. is there any user exit ..

I donot know but I wont expect that.

- .. is there a way to put a button into SE ..

I donot know

As other alternative you may try the classifcation system that is adding attributes externally to a development object. Maybe this link works better:

https://cw.sdn.sap.com/cw/docs/DOC-18775

Perdonne for all the bad news

Klaus

0 Kudos

My point here is, these properties are stored in the DB (SEOCLASSDF-RISK_LEVEL) which generates this pseudo-comments. So, you need to have something in SE24 or Custom Transaction to store these type of attributes and create them as pseudo-comments.

Well, the point was that if SE80 was not overwriting the headers in public/protected/private section we could do it without custom table by simply storing them directly in the source code (as comments).

This is the most natural way for a developer. Actually that's exactly how annotations started in Java language (by being special comments).

0 Kudos

To store the pseudo comments in the meta data would require the repository to get changed. I would be surprised uf such a change would be done as patch for shipped releases. It would not bet fortune that this will become true.

Actually I was not thinking about such BIG change because obviously as you stated, any changes to the repository are unlikely. The way I would see implementing it is:

- whenever someone edits a class in table editor the headers are already read and parsed (without paying attention to the comments)

- why don't we store the comments (but only in RAM) and whenever someone presses the Save button on the class (this triggers the overwrite of headers), we put those comments back (from RAM)

I don't know why you think that changes to the repository itself would be needed to make it work properly. Maybe there's some small detail I'm missing.

As other alternative you may try the classifcation system

Taken a quick look at this. It's the first time I see this. Anyway, I don't think it would be intuitive for the programmer (or handy) to input annotations there. So I won't be going in this direction.

Perdonne for all the bad news

No need to. This is exactly what we love about programming - you need to solve problems

0 Kudos

Hello Dominik,

first of all, thanks for sharing your code, thoughts, insights etc. about your DI implementation - very interesting!

I haven't had a chance to look at your code yet, but maybe you could briefly explain why you need the annotations (for constructor-injections) in the first place.

From the Guice docu I understand the @inject -annotation hints the framework to invoke the right (of possibly multiple) constructors when resolving dependencies. As we only have one constructor in ABAP anyway you wouldn't need this mechanism, right?

Regards,

Sebastian

0 Kudos

I haven't had a chance to look at your code yet, but maybe you could briefly explain why you need the annotations (for constructor-injections) in the first place.

From the Guice docu I understand the @inject -annotation hints the framework to invoke the right (of possibly multiple) constructors when resolving dependencies. As we only have one constructor in ABAP anyway you wouldn't need this mechanism, right?

We already [support|http://code.google.com/p/abap-di/wiki/SupportedFeatures] constructor injection without annotations. As you pointed out (proving that you indeed understand what I'm trying to achieve - thanks) we don't need annotations for constructor injection.

Just as I specified on our [roadmap|http://code.google.com/p/abap-di/wiki/Roadmap] we need it for fields/setters injection (but we could live without it) and most of all for named constants. This really blocks the code from using it productively.

Example. Suppose you have a class that takes a string as a parameter to constructor. Currently there's no way to work around this. To see how they do it in GUICE take a look at @Named annotation [here|http://code.google.com/p/google-guice/wiki/BindingAnnotations].

0 Kudos

first of all, thanks for sharing your code, thoughts, insights etc. about your DI implementation - very interesting!

Thanks. Most of what I see happening in ABAP world is writing SAP-scripts. Before I started with this library I was wondering whether there will be anyone (besides me) that is using ABAP as really object oriented language.

I'm very happy that there are some individuals that respond and continue the discussion. I would really love to see more people, but it seems that the reality is different

I haven't had a chance to look at your code yet...

You just caught me when I was updating the site. If you get a chance please have a look at [updated version|].

0 Kudos

Hello Dominik,

I am not too familiar with these Annotations yet, but it says somewhere in the Java docu

Annotations consist of ... and a parenthesized list of element-value pairs. The values must be compile-time constants.

So, the Binding Annoatation @Named you have pointed to cannot be the means to pass primitive (runtime) parameters to Guice-invoked constructors (?)

Could you please comment on the paragraph How do I pass a parameter when creating an object via Guice? in the FAQ section of Guice's docu; I have to admit I don't understand their example but at least for the title this should provide a solution to the issue we deal with here

Regards,

Sebastian

P.S. Could you publish your email-adress? I guess some of the details we might discuss are not really relevant/suitable for this forum (at least one would have to open a lot of new threads), so maybe we should exchange this via email.

0 Kudos

Most of what I see happening in ABAP world is writing SAP-scripts. Before I started with this library I was wondering whether there will be anyone (besides me) that is using ABAP as really object oriented language.

Don't worry, there are lots of ABAP OOers around, not quite as many as there are around Java, but we are picking up

0 Kudos

I am not too familiar with these Annotations yet, but it says somewhere in the Java docu

Annotations consist of ... and a parenthesized list of element-value pairs. The values must be compile-time constants.

So, the Binding Annoatation @Named you have pointed to cannot be the means to pass (runtime) parameters to Guice-invoked constructors (?)

Well, it's not like that. Let's speak Java. Suppose you have a constructor of class A


public A(@Named("parmvalue") String param1)

This java document you've found states that "paramvalue" (which is the only element of 'parenthesized list of element-value pairs') must be compile-time constant. And in fact it is.

Now, with guice you can do


bind(String.class).annotatedWith(Names.named("paramvalue")).toInstance("This is the actual value of my constructor parameter");

This is shown [here|http://code.google.com/p/google-guice/wiki/InstanceBindings] in the docs.

Could you please comment on the paragraph How do I pass a parameter when creating an object via Guice?

Exactly as I've shown above.

P.S. Could you publish your email-adress? I guess some of the details we might discuss are not really relevant/suitable for this forum (at least one would have to open a lot of new threads), so maybe we should exchange this via email.

It's now published in my profile

Edited by: Dominik Z on Dec 30, 2010 10:35 AM

0 Kudos

I see, so parmvalue is the "actual formal name" of the String-parameter param1 as far as Guice is concerned, thanks for the explanation.

I still hope though the annotations are no necessity You wrote

Suppose you have a class that takes a string as a parameter to constructor. Currently there's no way to work around this.

But why not pass the primitive parameters as a

abap_parmbind_tab

-table and provide a bind-method that is invoked in the configure-method say like

binding->to_primitives( act_params = <the_parameters> ).

(using your nomenclature where binding pertains to a class with primitive typed constructor parameters). The parameters are constructed like this


act_parm_bind-name = 'USER'.
act_parm_bind-kind   = 'E'.
user                           = sy-uname.

GET REFERENCE OF user INTO act_parm_bind-value.
INSERT act_parm_bind INTO TABLE the_parameters.

At the time the object is eventually constructed within the DI container the parameters are simply passed to a dynamic constructor call like

CREATE OBJECT return
    TYPE
      (class_name)
    PARAMETER-TABLE
      dyn_method_call_params.

I know, way uglier than the annotation-style, but it works. What do you think?

oops, posted "unready" by mistake, had to edit some more lines

0 Kudos

You might do it this way, but ask yourself a question: why was GUICE introduced in the first place?

The whole idea and name (dependency injection) goes from the fact that your're not biding one object to the other explicitly, but the framework does it implicitly.

If you would have introduced


binding->to_primitives()

then you would be binding one object (the primitives) to the other directly.

To give you an idea why what you've proposed is a bad idea. In one of our Java project we have jdbc connection string bound using the


 bind(String.class)
        .annotatedWith(Names.named("JDBC URL"))
        .toInstance("jdbc:mysql://localhost/pizza");

syntax exactly from GUICE docs. Now, there are a couple of objects using this URL since they create their own connections to the database. If this was bound directly to those objects you would need to repeat


binding->to_primitives()

again and again for each object using the primitive.

0 Kudos

Wow, that was fast..

I do not agree though. The main purpose of a DI container is to manage a certain object graph (induced by the class' dependencies). The objects/classes with primitive-typed parameters in their constructors form only the leaves of this graph. Providing those objects with their respective primitive parameters is more like a side job.

Besides your reasoning holds for value-objects only (special cases for my taste anyway). Plus in the example you have used you could introduce a dedicated jdbc_url -class which has (represents) the primitive parameter "jdbc:mysql://localhost/pizza" and on which in turn several other classes might depend on.

Regards,

Sebastian

0 Kudos

I do not agree though. The main purpose of a DI container is to manage a certain object graph (induced by the class' dependencies). The objects/classes with primitive-typed parameters in their constructors form only the leaves of this graph. Providing those objects with their respective primitive parameters is more like a side job.

Besides your reasoning holds for value-objects only (special cases for my taste anyway). Plus in the example you have used you could introduce a dedicated jdbc_url -class which has (represents) the primitive parameter "jdbc:mysql://localhost/pizza" and on which in turn several other classes might depend on.

It's more like an academic discussion. I will not make statements about whether GUICE developer did the right job or not. They handle primitives with annotations so that's how I wanted to do this in abap-di. Probably it's possible to figure out a workaround like you proposed, and that's probably what GUICE developers would do if they didn't have annotations.

But annotations are used in so many places in GUICE that I think having them would really become crucial in abap-di library.

To tease a little bit with what you're claiming. If we handle the example of URL connection with annotations, then we don't care which object will consume this 'leaf'. If we handle it like you proposed, then we do and we have to hard-code it. If in the future we move URL to some other object that will handle it (refactoring) we will need to change the code in two places.

0 Kudos

But annotations are used in so many places in GUICE that I think having them would really become crucial in abap-di library.

Good point, I understand why you are eager to construct something that resembles annotations.

If we handle the example of URL connection with annotations, then we don't care which object will consume this 'leaf'.

Hmm, not sure if this is true. With the @Named annotation you have to state the dependency explicitly ("hard code" as you put it) as well, like in your example

public A(@Named("parmvalue") String param1)

..the annotation being way more elegant than the clumsy parmbind-construction goes without saying.

And as for the refactoring, well, if that would affect even the relatively simple value-objects (like jdbc_url ) you are right.

Anyway, your strategy towards annotations is fair enough. As my comments are admittedly off-topic (considering the title of this thread) I suppose we continue via email if applicable.

Regards,

Sebastian

0 Kudos

Just came across your ABAP-DI implementation. Fascinating stuff.

I'm intrigued by the use of annotation, and while not yet having fully investigated the question, I wonder if you'd considered using macros to implement functionality as an alternative to the approach you describe.

The macros could be added to a type pool and the type pool be inserted into the forward declarations of the class definition.

This might allow dynamic generation of the binding code for example.

Apologies if I've misunderstood your issues.

0 Kudos

Just came across your ABAP-DI implementation. Fascinating stuff.

Thanks

I'm intrigued by the use of annotation, and while not yet having fully investigated the question, I wonder if you'd considered using macros to implement functionality as an alternative to the approach you describe...

The problem with annotations is that it is something you can tag every class/method/parameter with. If we were about to use other place than the class declaration header, then we would need to repeat the whole class definition. So, for instance if we wanted to say:

this is the annotation for METHODXYZ in CLASS123,

then this information would need to be repeated somewhere. This would cause problems when adding/removing methods from classes. That's why we wanted to do it the same way as is done in Java.

0 Kudos

Just a thought. Some of us are still working with older versions of SAP Basis. It would have been nice to have a DI container for earlier ABAP OO versions even if limited in scope or not quite Java

In any event, I tried to reproduce the issue with comments on our 7.00 SP13 system without success. The comments remain even when the CU include is edited using a variety of techniques including the back end line editor using SE38.

Was there a specific editor call approach you used that resulted in the zapped comments?

0 Kudos

Just a thought. Some of us are still working with older versions of SAP Basis. It would have been nice to have a DI container for earlier ABAP OO versions even if limited in scope or not quite Java

I'm also working commercially on older systems than EHP2. However, what is provided right now in abap-di project (http://code.google.com/p/abap-di) is not EHP2 dependent. Actually, even if we get the annotations working, it will not be EHP2 dependent, so you might be using it on 7.00 systems.

In any event, I tried to reproduce the issue with comments on our 7.00 SP13 system without success. The comments remain even when the CU include is edited using a variety of techniques including the back end line editor using SE38.

Was there a specific editor call approach you used that resulted in the zapped comments?

Thanks for your support in this. The comments disappear if you edit your class in the form-based editor (this is the default editor that you see when you open the class). So, as long as you keep editing only the source code of the CU directly (even using back end editor), you're fine. But the minute you for instance add a new method in the form-based editor, your CU source gets overriden.

Former Member
0 Kudos

We tested it on a system where SAP_ABA is Release 701 Level 0005. I've also checked that with the introduction of EHP2 (http://www.sdn.sap.com/irj/sdn/index?rid=/webcontent/uuid/1009fbb7-fd08-2d10-0182-852b6fa05f08&prtmode=print [original link is broken]) we will have a new editor that will not be table based (however, I don't have access to a system running EHP2).

My questions are:

- is there anyone running EHP2 that can check for me if any comment added to the public section of a class manually (Goto->Public Seciton) gets overridden, when you modify public section of a class by using the table-style editor

Just got my hands on EHP2. Turns out that the EHP2 behaves the same as EHP1 (meaning it overwrites the headers).