Quantcast
Channel: ABAP Development
Viewing all 948 articles
Browse latest View live

ABAP News for 7.40, SP08 - ABAP Managed Database Procedures (AMDP)

$
0
0

Recap

 

For code push down, meaning pushing analytics from the ABAP application server to the database server, you can use open ABAP features that run on any database. Those are Open SQL that was enhanced widely in ABAP 7.40 with analytic capabilities like SQL expressions or by removing restrictions from joins and the ABAP Core Data Services (ABAP CDS) for advanced view building in the ABAP Dictionary.

 

If the functionality offered by the open features is not sufficicient to cover your needs, you have to switch to Native SQL (sounds familiar?). This is especially true for SAP HANA, that offers analytical features not covered in standard SQL, as e.g. calculation views. If your ABAP programs should run on HANA  only (or if you want to offer special implementations for HANA and alternative implementations for other databases), database procedures written in SQLScript offer a convenient access to the capabilites of HANA. In order to facilitate this Native access to HANA, in 7.40, SP05 the concept of ABAP Managed Database Procedures (AMDP) was introduced, that allows you to code SQLScript in special methods of normal ABAP classes and the runtime environment does the rest for you. (But please note that a single SQL statement does not become faster if you code it in an AMDP, how should it? As long as you can stay open, stay open. There is no drawback in performance if you can express the logics in single statements or in CDS views. You use AMDP to avoid unnecessary data transfers between database and application server when using several statements or when you need access to fuctionality not covered by SQL).

 

 

News for ABAP 7.40, SP08

 

 

With ABAP 7.40, SP08, AMDP was enhanced as follows:

 

Tabular Changing Parameters

 

Although Native SQLScript procedures do not offer INOUT parameters, you can define CHANGING parameters for AMDP methods now. The trick is, that the database procedure generated from AMDP gets an additional IN parameter of the same name as the chaniging parameter with the pstfix __IN__ while the CHANGING parameter becomes an OUT parameter. When calling the procedure, the OUT parameter is filled implicitly with the CHANGING value passed to the IN parameter. Normally, you don't have to care about the implicit IN parameter. Only if you want to call such a procedure from another database procedure, you have to supply it.

 

AMDP method definition

 

METHODS

  get_carriers

     CHANGING

       VALUE(carriers) TYPE t_carriers

     RAISING  cx_amdp_error.

 

AMDP method implementation

 

 

  METHOD get_carriers BY DATABASE PROCEDURE FOR HDB

                         LANGUAGE SQLSCRIPT

                      USING scarr.

    carriers  = select s.*

                     from scarr as s

                     inner join :carriers as c

                       on s.mandt  = c.mandt and

                          s.carrid = c.carrid;

  ENDMETHOD.

 

A good example where AMDP is not needed at all, but KISS here.


Call from ABAP

 

TRY.   

    NEW cl_demo_amdp_changing(

      )->get_carriers( CHANGING carriers = carriers ).

  CATCH cx_amdp_error INTO DATA(amdp_error).

    ...

ENDTRY.

 

Class Based Exceptions

 

As shown above, you can handle exceptions that occur during processing an AMDP now. Before you got runtime errors only.

 

AMDP BAdIs

 

Special AMDP BAdIs allow you to implement BAdI methods as AMDP methods. These transfer the effect of the switches from Switch Framework to the implementation of database procedures in the current database. When an AMDP procedure calls another AMDP procedure managed by an AMDP BAdI, the implementation is executed that is prescribed by the current switch setting. (for calling AMDP procedures from ABAP no special BAdIs are necessary, because ABAP calls of normal BAdI methods are goverened by the switch framework anyway).


ABAP News for 7.40, SP08 - Optional Interface Methods

ABAP Unit Testing: Write expressive Test Code using the Builder Pattern

$
0
0

Why & when to use a Builder Class

A Test Method is divided in the 4 Parts: Setup, Exercise, Verify and Teardown (Meszaros).

 

Often you see that a huge and complicated part is the Setup, where you replace Dependencies with Test-Doubles to test a Class in Isolation. If you have complex Dependencies it is very easy to pollute your Test-Class with hundreds of lines of setup Code. If you want to test different scenarios, with different Input e.g. from Stubs, it get's even more worst.

 

One way to get around it would be the use of a mocking Framework that generates Code. I prefer self-written Stubs, Fakes or Mocks for different reasons.


To make Test-Classes shorter and more expressive I use often of Helper-Classes that use the "Builder Pattern". They can be a local Class if it is used for a single Test, or a global Class if it can be reused in several other Test's.

 

In the simplest case you just call the build Method, that creates a bound Instance to satisfy another Method to call - here with a Customer.

lcl_customer_builder=>new(

     )->build( ).

In simple human readable Text you can add Method's that set data for the instance to build.

lcl_customer_builder=>new(

     )->with_name(    

          'Max Mustermann'

     )->with_customer_id(

          '1234'

     )->build( ).


Also it is very comfortable if Class to build has own Dependencies you have to satisfy. Inside the Builder you can simply set them to Default or Null Implementations.


Without the Builder Pattern the Code may have looked like this:

DATA: lo_customer             TYPE REF TO lif_customer,    

           lo_fake_company     TYPE REF TO lif_company.

lo_customer =
     zcl_customer_factory=>get_instance(

          )->get_customer( '1234' ).

lo_customer->set_name( 'Max Mustermann' ).

 

lo_customer->set_company(

          zcl_company_factory=>get_company_null( )

     ).

 

An Example - Build a complex Fake Class

 

Test Class under Test and it's dependency


In our Example the Class under Test ZCL_EXAMPLE_CLASS_UNDER_TEST uses the Interface ZIF_DATE_OBJ_LOOKUP and it's Implementation ZCL_DB_DATE_OBJ_LOOKUP. For demonstration purposes it takes a Date and returns a generic Object Reference.

To test the Class ZCL_EXAMPLE_CLASS_UNDER_TEST in isolation we have to replace the use of ZCL_DB_DATE_OBJ_LOOKUP - that would access the Database.

 

Definition of ZIF_DATE_OBJ_LOOKUP

INTERFACE zif_date_obj_lookup
   PUBLIC .

   METHODS get_obj_for_date
     IMPORTING
       !i_date TYPE dats
     RETURNING
       value(r_obj) TYPE REF TO object .

ENDINTERFACE.

 

Our Class under Test ZCL_EXAMPLE_CLASS_UNDER_TEST

CLASS zcl_example_class_under_test DEFINITION
  
PUBLIC
   FINAL
  
CREATE PUBLIC .

  
PUBLIC SECTION.

    
METHODS:

          constructor,

          do_stuff

               RETURNING value(r_value) TYPE i.

   PRIVATE SECTION.

     DATA mo_date_obj_lookup TYPE REF TO zif_date_obj_lookup .

ENDCLASS.                    "ZCL_EXAMPLE_CLASS_UNDER_TEST DEFINITION

CLASS zcl_example_class_under_test IMPLEMENTATION.

  METHOD constructor.
    
CREATE OBJECT me->mo_date_obj_lookup
      
TYPE zcl_db_date_obj_lookup.
  
ENDMETHOD.                   

   METHOD do_stuff.
     " Uses the dependency ZIF_DATE_OBJ_LOOKUP
     me->mo_date_obj_lookup->get_obj_for_date( ... ).

  
ENDMETHOD.

ENDCLASS.                

 

The Fake Date Object Lookup Class

 

The Class lcl_fake_date_obj_lookup is the fake that will replace the Dependency for the class ZCL_DB_DATE_OBJ_LOOKUP. Instead the Original that use the Database, the Fake uses a Dictionary Class that returns an Object per Date.

CLASS lcl_fake_date_obj_lookup DEFINITION FINAL.

  
PUBLIC SECTION.

    
INTERFACES:
       zif_date_obj_lookup
.

    
METHODS:
       constructor
        
IMPORTING
           io_dictionary
TYPE REF TO zif_dictionary.

  
PRIVATE SECTION.

    
DATA:
       mo_fake_data_dictionary
TYPE REF TO zif_dictionary.

ENDCLASS.                   

CLASS lcl_fake_date_obj_lookup IMPLEMENTATION.

  
METHOD constructor.
     me
->mo_fake_data_dictionary = io_dictionary.
  
ENDMETHOD.                   

  
METHOD zif_date_obj_lookup~get_obj_for_date.
     r_obj
=
       me
->mo_fake_data_dictionary->get( |{ i_date }| ).
  
ENDMETHOD.                   

ENDCLASS.                   


The Fake Date Object Lookup - Builder


The Fake is build with the helper Class lcl_fake_date_lookup_bldr. This class contains logic to simplify the creation of Fakes with different Scenarios.  

CLASS lcl_fake_date_obj_lookup_bldr DEFINITION FINAL.

  
PUBLIC SECTION.

    
CLASS-METHODS:
      
new
         RETURNING
value(ro_self) TYPE REF TO lcl_fake_date_obj_lookup_bldr.

    
METHODS:
       constructor
,

       start_at_date
        
IMPORTING
           i_date
TYPE dats
         RETURNING
value(ro_self) TYPE REF TO lcl_fake_date_obj_lookup_bldr,
       ends_at_date
        
IMPORTING
           i_date
TYPE dats
         RETURNING
value(ro_self) TYPE REF TO lcl_fake_date_obj_lookup_bldr,
       returns_in_default
        
IMPORTING
           io_object
TYPE REF TO object
         RETURNING
value(ro_self) TYPE REF TO lcl_fake_date_obj_lookup_bldr,
       returns_at_date
        
IMPORTING
           i_date   
TYPE        dats
           io_object
TYPE REF TO object
         RETURNING
value(ro_self) TYPE REF TO lcl_fake_date_obj_lookup_bldr,
       build
         RETURNING
value(ro_fake_date_obj_bldr) TYPE REF TO zif_date_obj_lookup.

  
PRIVATE SECTION.

    
DATA:
           m_date_start                
TYPE dats,
           m_date_end                  
TYPE dats,
           mo_defalt_obj               
TYPE REF TO object,
           mo_dictionary_for_fake 
TYPE REF TO zif_dictionary.

    
METHODS:
       get_value_for_date
        
IMPORTING
           i_date
TYPE dats
         RETURNING
value(ro_obj) TYPE REF TO object,
       set_value_for_date
        
IMPORTING
           i_date   
TYPE        dats
           io_object
TYPE REF TO object
         RETURNING
value(ro_obj) TYPE REF TO object,
       is_value_for_date_set
        
IMPORTING
           i_date
TYPE dats
         RETURNING
value(r_is_set) TYPE abap_bool,
       get_dict_with_default_ret_obj
         RETURNING
value(ro_fake_dictionary) TYPE REF TO zif_dictionary.

ENDCLASS.                   

CLASS lcl_fake_date_obj_lookup_bldr IMPLEMENTATION.

  
METHOD new.
    
CREATE OBJECT ro_self.
  
ENDMETHOD.                   

  
METHOD constructor.
    
CREATE OBJECT me->mo_dictionary_for_fake
      
TYPE zcl_dictionary.
  
ENDMETHOD.                   

  
METHOD start_at_date.
     me
->m_date_start = i_date.
     ro_self
= me.
  
ENDMETHOD.                   

  
METHOD ends_at_date.
     me
->m_date_end = i_date.
     ro_self
= me.
  
ENDMETHOD.                   

  
METHOD returns_in_default.
     me
->mo_defalt_obj = io_object.
     ro_self
= me.
  
ENDMETHOD.                   

  
METHOD returns_at_date.
     me
->set_value_for_date(
         i_date   
= i_date
         io_object
= io_object
      
).
     ro_self
= me.
  
ENDMETHOD.                  

  
METHOD build.
    
ASSERT me->mo_defalt_obj  IS BOUND.
    
ASSERT me->m_date_end > me->m_date_start.

    
CREATE OBJECT ro_fake_date_obj_bldr
      
TYPE lcl_fake_date_obj_lookup
      
EXPORTING
         io_dictionary
= me->get_dict_with_default_ret_obj( ).
  
ENDMETHOD.                   

  
METHOD get_value_for_date.
     ro_obj
=
       me
->mo_dictionary_for_fake->get( |{ i_date }| ).
  
ENDMETHOD.                   

  
METHOD set_value_for_date.
     me
->mo_dictionary_for_fake->add(
        i_key  
= |{ i_date }|
        i_value
= io_object
     
).
  
ENDMETHOD.                   

  
METHOD is_value_for_date_set.
     r_is_set
=
       me
->mo_dictionary_for_fake->exists( |{ i_date }| ).
  
ENDMETHOD.                   

  
METHOD get_dict_with_default_ret_obj.
    
DATA: lv_current_date TYPE dats.

     lv_current_date
= me->m_date_start.

    
WHILE lv_current_date <= me->m_date_end.

      
IF me->is_value_for_date_set( lv_current_date ) = abap_false.
         me
->set_value_for_date(
             i_date   
= me->m_date_start
             io_object
= me->mo_defalt_obj
          
).
      
ENDIF.

       lv_current_date
= lv_current_date + 1.
    
ENDWHILE.

     ro_fake_dictionary
= me->mo_dictionary_for_fake.
  
ENDMETHOD.                   

ENDCLASS.                   



The Test Test-Class

CLASS ltcl_example_class_under_test DEFINITION
    
FOR TESTING
     DURATION SHORT
     RISK LEVEL HARMLESS
     FINAL
.

  
PRIVATE SECTION.

    
METHODS:
       get_test_instance
        
IMPORTING
           io_date_obj_lookup
TYPE REF TO zif_date_obj_lookup
         RETURNING
value(ro_fcut) TYPE REF TO zcl_example_class_under_test,

       test_3_days_with_one_problem
FOR TESTING,
       test_10_days_with_2_problems
FOR TESTING.

     "... more complex tests

ENDCLASS.                   

I decided to inject the Dependency by overwriting the Member Attribute after Construction. This way allows you to replace also local dependencies e.g. if you use a local Interface LIF_DB to extract SQL Commands to a local Class. And it is easy to create an Instance of the Class. To get access to the private Member Attribute I made the Test-Class to a Friend of the Class under Test.
But this has the Disadvantage that the Test knows internals of the Class Implementation and that the Constructor cannot contain Logic that uses the to replaced Dependency. A Clean way is to add the Dependency to the Constructor Parameters.

CLASS zcl_example_class_under_test DEFINITION LOCAL FRIENDS
            ltcl_example_class_under_test
.

The Test Implementation is reduced into the simple creation of the Instance - and the Assertions. Every Assert Statement contains the Builder Class - which tells the reader in simple readable Text the preconditions. I always try to reduce local Variables to a minimum to keep Methods short & clean.

CLASS ltcl_example_class_under_test IMPLEMENTATION.

  
METHOD get_test_instance.

    
CREATE OBJECT ro_fcut.
     ro_fcut
->mo_date_obj_lookup = io_date_obj_lookup.

  
ENDMETHOD.                   

  
METHOD test_3_days_with_one_problem.

     cl_aunit_assert
=>assert_equals(
        
exp= 3
         act
= me->get_test_instance(
                   lcl_fake_date_obj_lookup_bldr
=>new(
                    
)->start_at_date(
                      
'20140101'
                    
)->ends_at_date(
                      
'20140103'
                    
)->returns_in_default(
                       zcl_dummy2
=>new( )
                    
)->returns_at_date(
                       i_date   
= '20140102'
                       io_object
= zcl_dummy1=>new( )
                    
)->build( )
                
)->do_stuff( )
      
).

  
ENDMETHOD.                   

  
METHOD test_10_days_with_2_problems.

     cl_aunit_assert
=>assert_equals(
      
exp= 5
       act
= me->get_test_instance(
                   lcl_fake_date_obj_lookup_bldr
=>new(
                    
)->start_at_date(
                      
'20140201'
                    
)->ends_at_date(
                      
'20140210'
                    
)->returns_in_default(
                       zcl_dummy2
=>new( )
                    
)->returns_at_date(
                       i_date   
= '20140202'
                       io_object
= zcl_dummy1=>new( )
                    
)->returns_at_date(
                       i_date   
= '20140209'
                       io_object
= zcl_dummy1=>new( )
                    
)->build( )
                
)->do_stuff( )
    
).

  
ENDMETHOD.                   

ENDCLASS.                   

 

Conclusion

 

The Builder Pattern is another Tool in my Toolkit for Test-Driven Development. Complex Dependencies are often a signal that there's something wrong with your Class Design, but you often have to test Classes that must be tested with varying values - and a builder can help you with that.

The Builder Class in the Example above contains quite a bit of logic - and untested logic as dependency for your class under Test may result in brittle Test's. So you may have to test that logic as precondition before the actual Test's. If you use a complex global Builder Class, it would contain own Test's in it's local Test-Class Include.

Isolate components for better testing with mockA

$
0
0

Introduction

This blog post is strongly connected to the presentation that has been given by Damir Majer and Martin Steinberg during SAP Inside Track 2014 in Munich.

The presentation focuses on solving a code kata using Test-Driven Development (TDD).

The purpose is to show how TDD can lead to better tests coverage, thus more robust and maintainable software components. This blog post focuses not about the solution of the code kata itself, but rather on how to test each component separately from each other using mockA.

 

The Kata

Summarized, the Kata says:

Implement a simple String calculator class that accepts a flexible amount of numbers in a string. The numbers should be summed up and the sum needs to be returned.

Examples:

  • An empty string returns “0”
  • For single numbers, the number itself will be returned, e.g. for “1”, the sum 1 will be returned
  • For “1,2”, the sum 3 will be returned
  • Also multiple delimiters will have to be accepted, e.g. “1;2\3;1” will lead to 7
  • This also applies to line breaks like “\n”. “1\n2,3” results in 6
  • Delimiters might have variable length. "//***\1***2***3\2***2” results in 10
  • Raise an exception in case negative numbers are passed to the method
  • Numbers bigger than 1000 should be ignored

The Kata requires you to implement the code step by step, without skipping steps. Every step should contain

  • A unit test that tests the requirement and will fail at the first run
  • An implementation that covers the requirement
  • A new unit test run that will succeed
  • Refactoring
  • Running the test again to ensure nothing broke

 

The Solution

The solution class can be found in the attachments (“zcl_string_calculator.txt”).

The class ZCL_STRING_CALCULATOR contains

  • One protected method that replaces all delimiters with a comma (“replace_delimiter_with_comma”)
  • One protected method that sums up the consolidated string (“compute”)
  • One public method to rule them all (“add”)
  • Several attributes

“add” basically delegates the task of replacing all delimiters with commas to a specific protected method. It uses its output to sum up the values.

The Unit Test report “Unit Test v1.txt” shows the corresponding unit tests.

 

Isolate helper methods from the add-method

While “replace_delimiter_with_comma” and “compute” are helper methods, the public “add”-method delegates its own calls to these methods. Thus, it is dependent from the helper methods.

In some point of time, it might be helpful to check, if the “add”-method works as expected, which means, that it delegates its calls correctly to the helper method.

Think of the following unit test, which does not directly link to the code kata, but may ensure code quality:

  • Test the “add” method with the string “<1sd2,3rtrt,4”
  • Ensure, that “add” calls “replace_delimiter_with_comma” with “<1sd2,3rtrt,4”
  • The call will return “1,2,3,4”
  • Ensure, that “compute” will be called with “1,2,3,4”
  • Ensure, that the output of compute is returned without modification (result will be 10)

Such a test will need you to subclass ZCL_STRING_CALCULATOR and redefine the helper methods with hard coded return values based on specific inputs. Furthermore, some logic behind “compute” should allow you verify if the method has been called with the correct parameters.

Subject to the test will be the subclass of ZCL_STRING_CALCULATOR, which will partly contain so called faked functionality regarding “replace_delimiter_with_comma”. But it will also contain some mock features, as “compute” should not only conditionally return some values based on its input, but it should also allow you to determine, if it has been called with the expected input.

mockA allows you to skip this subclassing and lets you focus on the test. It will create a subclass at runtime for you, which follows constraints like conditional method output. These constraints can be hard coded by you. It will also allow you to verify method calls of mocked methods.

“Unit Test v2.txt” shows you how to do it. Keep a look a test method “test_add”.

The first call

    lo_mocker = zcl_mocka_mocker=>zif_mocka_mocker~mock( 'ZCL_STRING_CALCULATOR' ).    lo_mocker->method( 'replace_delimiter_with_comma'      )->with_changing( '<1sd2,3rtrt,4'      )->changes( '1,2,3,4'    ).
tells mockA to fake the method “replace_delimiter_with_comma”, while    lo_mocker->method( 'compute'      )->with( '1,2,3,4'      )->returns( 10    ).

tells mockA to fake the output of “compute”.

Subject to the test will be the object generated by mockA (which is a subclass of ZCL_STRING_CALCULATOR in reality)

    go_string_calculator ?= lo_mocker->generate_mockup( ).

After the call of “add”, the result is verified in the unit test. But besides this verification, you may also ensure, that “compute” has been called correctly with the input value “1,2,3,4”:

    DATA lv_has_been_called_correctly TYPE abap_bool.    lv_has_been_called_correctly = lo_mocker->method( 'compute' )->has_been_called_with( '1,2,3,4' ).    assert_not_initial( lv_has_been_called_correctly ).

 

Further information

You may find further information of the presenters at

damir-majer.com / @majcon

http://about.me/martin.steinberg / @SbgMartin

attachments: / - uwekunath-wordpress-com - attachments for blog posts - Google Project Hosting

ABAP Language News for Release 7.40, SP08

$
0
0

Release 7.40, SP08 of Application ABAP in SAP Netweaver is another bundled release that comes with a new kernel. While 7.40, SP02 was delivered with kernel release 740 and  7.40, SP05 with kernel release 741, 7.40, SP08 is based on kernel 742. When upgrading your 740 application server to 7.40, SP08 you have to use kernel 742 and by this you will get the following enhancements of the ABAP language in a fully downward compatible way.

 

Expressions

  • Predicative method call IF meth( ) and a new boolean function xsdbool for logical expressions
  • Iterative expressions FOR ... UNTIL|WHILEin constructor expressions, new constructor expression REDUCEespecially for FOR
  • Addition BASEfor start values of constructor expressions

 

 

Internal Tables

 

Database Access

  • Inline declarations, enhanced SQL expressions and new position of INTO clause in Open SQL
  • Parameter views, new built-in functions and view extensions in  ABAP CDS
  • Tabular changing parameters, class based exceptions and specialized BAdIs in AMDP

 

 

Furthermore, you can make interface methods optional now. As always, you find all ABAP News in the ABAP Keyword Documentation, that was updated in the SAP Help Portal. The updated version contains a new reference documentation for the ABAP Dictionary. The next bundled release with new ABAP features (I know some niceties already)  will be 7.40, SP12 presumably.

Adding UAN Number to PaySlip - Enhancing HINCEDTO Program

$
0
0

Employees Provident Fund Organisation, India (EPFO) has launched a Universal Account Number (UAN) to provide a number of facilities to its members through a single window. In SAP a new subtype 08 ( Universal Account Number ) has been created for Infotype 185 to store Universal Account number.

 

Basically we design payslip through HR form editor ( Tcode PE51 ) and we add tables, fields to HR Form classes (PE51_Checktab).

Once the table and fields are added, this will bring the value into the payslip but in this case UAN number is stored in 0185 as ICNUM and is classified by subtype 8 so we cannot directly put the fields in PE51_Checktab to fetch the UAN Number on Indian Payslip. We have to make a Z enhancement (Implicit Enhancement) to incorporate UAN number on Payslip.

 

The standard program HINCEDT0 will be called while generating indian payslips through Tcodes PC00_MXX_CALC and PC00_MXX_CEDT. If you want to this display this UAN number on Indian Payslip, we need to enhance this program.


Open HINCEDTO in SE38 and enhance include RPCEDDZ9 for data definitions and also enhance Include RPCEDSZ9 to write our own code ( in this case to fetch UAN number based on subtype).


29.jpg

26.jpg

27.jpg

 

Finally we will add additional structure TUAN and their respective fields ICNUM and SUBTY which we added by enhancing RPCEDDZ9, to form Class ( PE51_CHECKTAB) so they become available in HR Form Editor (PE51) for payslip designing.

 

25.jpg

23.bmp

 

Useful Links :

 

**************** - Payslip through PE51 – adding custom fields from infotypes

 

EPFO Launched Universal Account Number

 

*****************************************************************************************************************************************************************************************

Your feedback is highly appreciated, Thank you,

 

PRADEEP K

 

*****************************************************************************************************************************************************************************************

Vesna Hello World Application

$
0
0

A working example is worth hundreds pages of documentation. Hence, let me entertain you today with a simple yet powerful Vesna Hello World application, demonstrating basic Vesna application composition capabilities. I don't want to keep you waiting so let's just install and run it.

First Steps

If you do not have Vesna Framework installed yet, it's high time to do it. You can find an awfully long manual here - please do not read the whole of it, the short version will do just fine.

The installation procedure for this Vesna Hello World application can hardly be made any easier:

  1. Download source code file ZVESNA_HELLO_WORLD.txt attached to this blog post
  2. Create report ZVESNA_HELLO_WORLD in your ABAP NW system where you have Vesna installed:
    ActionImage
    Create Programscreenshot041.png
    Defaults will do just finescreenshot042.png
    Save locallyscreenshot043.png
    Copy-paste the contents from attached source code filescreenshot044.png
  3. Activate the report
  4. Enjoy your Vesna Hello World application:

screenshot045.png

That's it. No classes to install, nothing. The demo uses two classes present in any system running Vesna, being:

  • CL_OS_SYSTEM
  • CL_ABAP_OBJECTDESCR

Vesna Application Composition

The application instantiates an object of type CL_OS_SYSTEM (under bean name of sys) and passes this instance to a factory method CL_ABAP_TYPEDESCR=>DESCRIBE_BY_OBJ_REF( ), obtaining a reference to an object of type CL_ABAP_OBJECTDESCR as rtts bean. This concludes the application composition part of the application.

Application Logic

This part has nothing to do with presenting Vesna Framework and merely proves that we actually have obtained a fully configured object. What we do is list methods of our sys bean. Easy-peasy.

More detail, please!

Let's jump straight to the point where we find some action: method application=>handle_sapevent. If you have copy-pasted the report ZVESNA_HELLO_WORLD, this will be line 212 of the code. As soon as you press the button (or more precisely, The Button as there is only one), that's where you land.

The first thing is to bring your Vesna application container to life. You will do that by feeding the constructor of the /ARCONA1/APPLICATION_CONTEXT class with an iXML input stream (IF_IXML_ISTREAM). iXML library offers us a few wonderful options to do this by the means of loading XML from file, text string, binary string, internal table and so on. The example in line 225 of the ZVESNA_HELLO_WORLD shows one of many possibilities. You can learn how to do it in a different way by the means of consutling SAP iXML library documentation in the SAP Help portal. I'm not providing the link since they usually don't work. Just google for it. Anyway, in most usable scenarios reading an XML input of any sort and converting it to an iXML input stream is a matter of a nice one-liner.

 

Where were we? Ah yes, getting hold of the application container. And in fact, that's just about it. Unless you want to register any objects existing already in this pre-context of your application, you can go and request your business logic handle right away. You'll do that by the means of querying the GET_BEAN method of the Vesna application container with the bean name that is of interest to you. This should be something like a single point of entry to your application so that you don't have to refer to Vesna bindings any more. This is what happens in the line 230 of the ZVESNA_HELLO_WORLD report. Beyond this line, the application is all yours: do with it whatever you like.

 

Side Effects

Now, let's hold on for a moment and consider the collateral damage;) that will be inflicted by the use of Vesna application composition as compared to static coding.

 

Great Testability

The application we're accessing knows only one thing: all the dependencies are simply there. It does neither know or care what exactly types they are or what their internal logic is. This means, we can very easily test any given object in full isolation but retaining its functionality as long as we provide (via Vesna configuration) some compatible dependencies so that tested object "thinks" that it works in a true environment. In other words, mock testing is at hand.

Native Extensibility

Just in the same way we can pick & mix standard and custom implementations for any given application without changing a single line of the original code. This is the ultimate technology for customer extensions, allowing you to plug in just about anywhere in the code and yet change nothing.

 

Transparent Application Structure

Have you ever wondered, looking at your SE80 package structure, what the application really needs and where? Well, the days of such pondering are over with Vesna. The beans are laid out in front of you, nicely interlinked via ref tokens. In a typical code you would also have some runtime variables preconfigured as well and passed to the application via value tokens. Also, you'd probably make good use of setter methods apart from constructor arguments.

 

Really Good OO Code

Vesna will very quickly start changing your way of thinking about code and suggest you excellent OO design, without any effort from your side. Especially in ABAP OO with its extraordinarily elaborate code, you'll be no longer tempted to create monster classes in order to avoid lots and lots of coding just in order to provide for plumbing & welding for your application. Vesna will do that all for you, out the box and you can only concentrate on the functionality at hand.

 

Zero Footprint

Basic Vesna usage has barely measurable footprint as it does not generate anything and relies solely on runtime object properties. Therefore it is lightning fast and absolutely safe to use in any environment.

 

No Strings Attached

This very demo applications shows that Vesna works just fine with any plain old ABAP Objects, not implementing any special interfaces or inheriting from any special classes. Feel free to use it the way you like.

 

Summary

This is but a trivial and completely unproductive sample of a Vesna application. It is solely up to you to venture something more challenging. However, real adventure begins with AOP coding in ABAP OO which I'll show to you next time.

Stay tuned!

Exit Debugger without database update

$
0
0

Just a debugging tip I want to share.

 

I was debugging a transaction which updates database. Suddenly I realized that the selection parameters I have given in the selection screen were wrong. So to prevent database update,

There is an option provided in the debugger, Which is EXIT APPLICATION AND DEBUGGER.

The problem with that option is it exits application and debugger but all the updates happened till that point of time were committed.

 

The work around:

 

  • Switch to classic debugger.

Capture1.JPG

 

  • Then Restart.

 

Capture2.JPG

 

  • You will be redirected back to Transaction screen.

 

Capture3.JPG

 

These steps will prevent from updating the database.


Export ALV-Tree to Excel with XLSX Workbench

$
0
0
related page


NOTE: Before beginning, the XLSX Workbench functionality must be available in the your system.

 

Let's use standard demo report BCALV_TREE_02 is available in the every system (the report demonstrates how to use ALV-Tree control). We export this ALV-tree to the Excel based form.

 

1 PREPARE A PRINTING PROGRAM.

 

1.1 Copy standard demo report BCALV_TREE_02 to the customer namespace, for example Z_BCALV_TREE_02 :

444_5.PNG

 

 

1.2 In the copied report, add new button to GUI-status 'MAIN100':

444_14.PNG

 

 

1.3 In the report line number 29, write CL_HRPAYNA_GUI_ALV_TREE instead CL_GUI_ALV_TREE :

444_8.PNG

 

 

1.4 In the report line number 125, insert next code to processing the new OK-code :

444_112.PNG

 

1.5 Activate objects:

444_15.PNG

 

 

 

2 PREPARE A FORM.

 

2.1 Launch XLSX Workbench, and in the popup window specify a form name TEST_ALV_TREE , and then press the button «Process»:

444_19.PNG

Empty form will be displayed:

444_19_1.PNG

2.2 Push button444_19_2.PNGto save the form.

 

 

2.3 Assign context CL_HRPAYNA_GUI_ALV_TREE to the form:

444_19_55.PNG

 

2.4 Add new sheet to a form:

444_19_56.PNG

 

 

2.5 Assign created Sheet to worksheet in the Excel-template:

444_19_57.PNG

 

2.6 Add a Tree to the Sheet:

444_201.PNG

 

2.7 Assign created Tree to the context:

444_23.PNG

 

2.8 Make markup in the Excel template (read more here):

444_24.PNG

 

2.9 Assign Tree to the marked area (cells range A1:B5) in the Excel template.

To do that, select cells range A1:B5 in the Excel template, and then, press button with "pencil" in the item "Area in the template" of the Properties tab:

444_28.PNG

2.10 Activate form by pressing button444_30.PNG.

 

 

 

3 EXECUTION.


Run your report Z_BCALV_TREE_02; ALV-tree will be displayed :

444_41.PNG


Press button444_43.PNGto export ALV-Tree to Excel form :

444_42.PNG

Easy to Send Excel Attachment via Email from SAP

$
0
0

Several times everybody must have been come cross the requirement that from SAP a file has to be created as per the required template and send to Third part system to process over there.

 

For this scenario, if the any centralized file system is there where SAP and Third party system have been connected , the file can be sent to File system and from there the third part can pick file to process in the system.

 

Unfortunately Centralized file system is not there in that case the file can be sent via email to third party team. By using old Function Module SO_DOCUMENT_SEND_API1  itself easily the excel file can be sent via email as attachment.

 

Check below code and try yourself.

 

 

 

REPORT sy-repid.


DATA:     li_attach  TYPE TABLE OF solisti1,

          li_message
TYPE TABLE OF solisti1,

          li_receivers
TYPE TABLE OF somlreci1,

          lw_attach 
TYPE solisti1,

          lw_message
TYPE solisti1.



DATA:    ld_mtitle TYPE sodocchgi1-obj_descr,

          ld_format
TYPE  so_obj_tp ,

          ld_attdescription
TYPE  so_obj_nam ,

          ld_attfilename
TYPE  so_obj_des ,

          ld_sender_address
TYPE  soextreci1-receiver,

          ld_sender_address_type
TYPE  soextreci1-adr_typ.



 
DATA:   t_packing_list TYPE sopcklsti1 OCCURS 0 WITH HEADER LINE,

          t_receivers
TYPE somlreci1 OCCURS 0 WITH HEADER LINE,

          t_attachment
TYPE solisti1 OCCURS 0 WITH HEADER LINE,

          w_cnt
TYPE i,

          w_doc_data
TYPE sodocchgi1.





 
CONSTANTS:

   con_tab 
TYPE c VALUE cl_abap_char_utilities=>horizontal_tab,

   con_cret
TYPE c VALUE cl_abap_char_utilities=>cr_lf.




*-------Populate Headings data for Excel File-------*

 
CONCATENATE 'Employee Number'

             
'Employee Name'

             
'Employee Address'

             
INTO lw_attach SEPARATED BY con_tab.

 
CONCATENATE con_cret lw_attach  INTO lw_attach.

 
APPEND  lw_attach TO li_attach.

 
CLEAR : lw_attach.


*----Populate Actual data for Excel file--------*



   
CONCATENATE '123421'

               
'Somu'

               
'Bangalore'

               
INTO lw_attach SEPARATED BY con_tab.



   
CONCATENATE con_cret lw_attach  INTO lw_attach.

   
APPEND  lw_attach TO li_attach.

   
CLEAR : lw_attach.



   
CONCATENATE '123423'

               
'Sasi'

               
'Bangalore'

               
INTO lw_attach SEPARATED BY con_tab.



   
CONCATENATE con_cret lw_attach  INTO lw_attach.

   
APPEND  lw_attach TO li_attach.

   
CLEAR : lw_attach.





 
REFRESH li_message.

 
CLEAR : lw_message.



  lw_message
= 'Email Body'.

 
APPEND lw_message TO li_message.

 
CLEAR : lw_message.



  lw_message
= 'Thanks & Regards'.

 
APPEND lw_message TO li_message.

 
CLEAR : lw_message.



  lw_message
= 'Raju C D'.

 
APPEND lw_message TO li_message.

 
CLEAR : lw_message.


* Email Sending



  ld_mtitle
= 'Employee Details'.

  ld_format
= 'XLS'.

  ld_attfilename
= 'ATTACHMENT'.

  ld_attdescription
= 'Emp_Details'.


* Fill the document data.

  w_doc_data
-doc_size = 1.


* Populate the subject/generic message attributes

  w_doc_data
-obj_langu = sy-langu.

  w_doc_data
-obj_name  = 'SAPRPT'.

  w_doc_data
-obj_descr = ld_mtitle .

  w_doc_data
-sensitivty = 'F'.


* Fill the document data and get size of attachment

 
CLEAR w_doc_data.

 
READ TABLE li_attach INTO lw_attach INDEX w_cnt.

  w_doc_data
-doc_size =

    
( w_cnt - 1 ) * 255 + STRLEN( lw_attach ).

  w_doc_data
-obj_langu  = sy-langu.

  w_doc_data
-obj_name   = 'SAPRPT'.

  w_doc_data
-obj_descr  = ld_mtitle.

  w_doc_data
-sensitivty = 'F'.

 
CLEAR t_attachment.

 
REFRESH t_attachment.

  t_attachment[]
= li_attach[].


* Describe the body of the message

 
CLEAR t_packing_list.

 
REFRESH t_packing_list.

  t_packing_list
-transf_bin = space.

  t_packing_list
-head_start = 1.

  t_packing_list
-head_num = 0.

  t_packing_list
-body_start = 1.

 
DESCRIBE TABLE li_message LINES t_packing_list-body_num.

  t_packing_list
-doc_type = 'RAW'.

 
APPEND t_packing_list.


* Create attachment notification

  t_packing_list
-transf_bin = 'X'.

  t_packing_list
-head_start = 1.

  t_packing_list
-head_num   = 1.

  t_packing_list
-body_start = 1.



 
DESCRIBE TABLE t_attachment LINES t_packing_list-body_num.

  t_packing_list
-doc_type   ld_format.

  t_packing_list
-obj_descr  ld_attdescription.

  t_packing_list
-obj_name   ld_attfilename.

  t_packing_list
-doc_size   t_packing_list-body_num * 255.

 
APPEND t_packing_list.


* Add the recipients email address

 
CLEAR t_receivers.

 
REFRESH t_receivers.



    t_receivers
-receiver = 'rajucd81@gmail.com'.

    t_receivers
-rec_type = 'U'.

    t_receivers
-com_type = 'INT'.

    t_receivers
-notif_del = 'X'.

    t_receivers
-notif_ndel = 'X'.

   
APPEND t_receivers.



  li_receivers[]
= t_receivers[].


* FM to sent Email with Attachment

 
CALL FUNCTION 'SO_DOCUMENT_SEND_API1'

   
EXPORTING

      document_data             
= w_doc_data

      put_in_outbox             
= 'X'

      sender_address            
= ld_sender_address

      sender_address_type       
= ld_sender_address_type

      commit_work               
= 'X'
*    IMPORTING
*      sent_to_all                = w_sent_all

   
TABLES

      packing_list              
= t_packing_list

      contents_bin              
= t_attachment

      contents_txt              
= li_message

      receivers                 
= t_receivers

   
EXCEPTIONS

      too_many_receivers        
= 1

      document_not_sent         
= 2

      document_type_not_exist   
= 3

      operation_no_authorization
= 4

      parameter_error           
= 5

      x_error                   
= 6

      enqueue_error             
= 7

     
OTHERS                     = 8.



 
IF sy-subrc eq 0.

   
WRITE:' Email has been sent successfully'.

 
ENDIF. 

Lazy initialization in ABAP

$
0
0

"In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed." (Wikipedia)

 

A very unused yet extremely simple software design technique is the lazy initialization (sometimes referred to as lazy instantiation or lazy loading). This is exceedingly helpful in large applications where a massive amount of data must be loaded and/or calculated at runtime.

 

For a better understanding, the following ABAP scenario is taken into consideration:

A company/client needs an application to display all the information related to a single entity model. Because the amount of that cannot fit into a single database table or a single screen, a decision has been taken to implement the display in the form of a tab strip, where each of the tabs will encapsulate information in different forms with the possibility to integrate different data sources (E.g. entry/entries from the underlying or external database, calculations, aggregates, RFC calls, Web Services, etc.).

 

In this example, several database tables will be used, each will correspond to one of the tabs:

tabs and data sources.png

The database objects will be uniquely identified by a key value structure, which will be referred to as the "common key". When the application is started and the tab strip is instantiated, the only known data is:

  1. The common key
  2. ID of the first displayed tab

(For clarity purposes, each data source will be named according to the corresponding tab: D1, D2 and so on.)

 

Because the business logic must be UI-independent, the application will be structured in two packages:

  1. Business object (BO) layer – encapsulates the data model and functionality
  2. User interface (UI) layer

 

Using a bottom-up approach, the BO layer will be designed first. For each data sources (in this case: ZD1, ZD2, etc.) a corresponding business class must be created.

bo architecture.png

ZCL_FACTORY will act as a bottleneck for the creation of the subordinate objects, which can only be instantiated by the factory method.

As the factory class contains a list of already instantiated BOs, it should also be a Singleton. The factory's constructor method is optional, but it can be used for example to either enqueue existing data in Change-mode or generated the common key in Create-mode.

 

A snippet of the ZCL_FACTORY class with some explanations:


CLASS zcl_factory DEFINITION
                 
PUBLIC

                                       FINAL

                  CREATE PRIVATE.

PUBLIC SECTION.
CLASS-METHODS get_instance
  
IMPORTING
    
value(iv_common_key) TYPE guid OPTIONAL
   RETURNING
    
value(ro_factory) TYPE REF TO zcl_factory.

METHODS constructor
  
IMPORTING
    
value(iv_common_key) TYPE guid OPTIONAL.

METHODS factory
  
IMPORTING
    
value(iv_type) TYPE string
   RETURNING
    
value(ro_bo) TYPE REF TO zcl_abstract_bo.

PRIVATE SECTION.
TYPES:
  
BEGIN OF ts_list,
     classname
TYPE classname,
     bo 
TYPE REF TO zcl_abstract_bo,
  
END OF ts_list,
   tt_list
TYPE STANDARD TABLE OF ts_list.

CLASS-DATA :
   mo_factory
TYPE REF TO zcl_factory.

DATA :
   mt_list      
TYPE tt_list,
   mv_common_key
TYPE guid.
ENDCLASS.


CLASS zcl_factory IMPLEMENTATION.
METHOD constructor.
   mv_common_key
= iv_common_key.
ENDMETHOD.

METHOD factory.
  
DATA :
     lv_classname
TYPE classname.

FIELD-SYMBOLS :
   <fs_list>
TYPE ts_list.

*   Obviously these hard-coded values are not optimal
CASE iv_type.
  
WHEN 'D1'
    
OR 'D2'
    
OR 'Dx'.
       lv_classname
= |ZCL_BO_{ iv_type }|.
  
WHEN OTHERS.
*      RAISE EXCEPTION TYPE ...
ENDCASE.

*   Check if the list already contains an instance
READ TABLE mt_list ASSIGNING <fs_list>
                   
WITH KEY classname = lv_classname.

*   If not, create
IF NOT sy-subrc IS INITIAL.
  
APPEND INITIAL LINE TO mt_list ASSIGNING <fs_list>.
   <fs_list>
-classname = lv_classname.
  
CREATE OBJECT <fs_list>-bo TYPE (lv_classname)
    
EXPORTING
       iv_common_key
= mv_common_key.
ENDIF.

*   Return BO instance
   ro_bo
= <fs_list>-bo.
ENDMETHOD.

METHOD get_instance.
*   Singleton method to retrieve factory instance
IF mo_factory IS INITIAL.
*    Just as an example for Create/Display
  
IF iv_common_key IS SUPPLIED.
    
CREATE OBJECT mo_factory
      
EXPORTING
         iv_common_key
= iv_common_key.
  
ELSE.
    
TRY.
      
CREATE OBJECT mo_factory
        
EXPORTING
           iv_common_key
= cl_uuid_factory=>create_system_uuid( )->create_uuid_x16( ).
    
CATCH cx_uuid_error.
*        ...
    
ENDTRY.
  
ENDIF.
ENDIF.

   ro_factory
= mo_factory.
ENDMETHOD.
ENDCLASS.

 

Note: Attribute MT_LIST can also be used as a mechanism to control methods like: SAVE, CHECK_BEFORE_SAVE, HAS_CHANGES, and so on; but this depends on particular scenarios.

 

At this point, each specific BO can be implemented to match the particular use case.

  1. E.g. ZCL_BO_D1 reads a single entry from the database and displays it as a form. Therefore each field will have corresponding getter and setter methods. Alternatively, ZCL_BO_D2 will select a number of rows from the database and output them as a table. In which case, CRUD functionalities might be more adequate.

The constructor of each BO is responsible to load the data buffer using the given common key.

 

Note: As all the business objects have the property CREATE PRIVATE, each one must declare ZCL_FACTORY as friend.

 

The following statement can be used to create a BO instance for D1:


DATA:
lo_bo
TYPE REF TOzcl_bo_d1.

lo_bo ?= zcl_factory
=>get_instance( )->factory( 'D1' ).


After the business logic is active and secured, it is time to move up towards the UI layer. For this example, the user interface has been implemented both as an ABAP report and a Web Dynpro application. Nevertheless any other UI technology can be used.


1. ABAP Report

The most elementary implementation requires a main screen (100) and two sub screens (101, 102). The latter are embedded into a tab strip control belonging to the main screen. The trick here consists of adding the BO instantiation in the PBO module of each sub screen. As the PAI module of screen 100 controls the tab strip actions, the corresponding PBO modules are only called upon when necessary. This means that data is only loaded when displayed.

 

2. Web Dynpro Application

The application consists of a main WD component with a start view and an embedded TabStrip UI element. Based on the complexity of the application, it is a matter of choice how each tab is implemented:

     2.1. Directly in the same view

     2.2. As a different view inside the same application

     2.3. As a separate WD component

 

Either way, the component controller (from the main component 2.1., 2.2., or the each used component, 2.3.) must implement initialization method(s) – for 2.3., these methods must be defined as interface.

The catch in this situation is that TabStrip UI element has an event called ON_SELECT. For this event, an associated event handler is implemented in the start view of the main component. Similar to the PAI module, this method is used to determine the navigation and therefore control the BO instantiation.

 

METHOD onactionon_select.
 
CASE wdevent->get_string( 'TAB' ).
   
WHEN 'D1'.
   
WHEN 'D2'.
*     2.1., 2.2.
      wd_comp_controller
->init_d2( ).
*     OR

*     2.3.
      wd_this
->wd_cpifc_d2( )->init( ).
   
WHEN 'Dx'.
 
ENDCASE.
ENDMETHOD.

 

Note: This can also be implemented using Floorplan Manager (FPM) as an OIF component by checking the navigated tab in method PROCESS_BEFORE_OUTPUT.

 

Evidently, it is important to set the most used tab as initial or give the possibility for the user to choose.

 

In the end, this is the most rudimentary example I could think of, but it can nevertheless be scaled tremendously.

 

 

Thank you and please feel free to contribute. My only hope is that I didn't compress the content to the extent that it is not understandable.

 

Tudor

Venturous Logging Solution for ABAP OO: Vesna AOP Demo Case

$
0
0

Quite recently I've been impressed by a blog post by Eric Petersen, describing a better logging solution for ABAP OO. However, while this approach definitely addresses quantitative part of the problem, in terms of squashing the code a bit, I could not help thinking that this is something like buying a better porcelain in a diarrhea case. It will simply not cure the illness, no matter how hard you try.

 

So, what's the cure then?

The first and most important question is, when writing an application, any application - are we really interested in logging? Yes, logging is something we must take care of at some point, just like authorization checks, possibly also tracing and lots of other stuff, but is this really supposed to be a concern of mine as an application author? Does the log handling really need to clutter my shiny application code?

 

The keyword is Concern

...Or, more precisely, separation of concerns. After all, logging presents such a brilliant example of a cross-cutting concern which bubbles all around the place. In fact, we can never be sure that we're not going to need logging at any specific point in code later, some time in the future. Neither can we predict that we might need to log some more stuff in certain cases while some places we have decided earlier in the project to do the logging are not really needed any more and could be cleaned up.

So what do we do? Refactor and refactor to death? Well, I don't know how about you but I hate such menial manual jobs, not to speak of the likelihood to do something wrong and be forced to come back to the same place in the code again and again. That's no fun.

 

C'mon, show me the solution!

Enough small talk. Besides, the RIGHT logging solution is not rocket science and only requires a tiny bit of AOP. Yes? That ABAP does not support AOP? Maybe it does not, maybe it does... It depends mostly if you have Vesna Framework installed in your NetWeaver system (which needs to be at least 7.02 or higher).

If you don't, follow this link to the blog post about Vesna installation (it's free for research and non-commercial use), install it in no time and come back here. Then you can download the demo source code attached to this blog post and see how you can get rid of logging code from your application altogether and yet, log anything you want, anywhere you want. Moreover, your decisions do not have to be final, neither you are bound to any specific implementation of the logger. Does it sound like a fairly tale? A good one, possibly? But you may wake up. Really. Vesna AOP does give you all this, and much more.

 

Download & Install

Don't just read. Try it. If you see the code in action and feel it, you will immediately embrace the power of an AOP programming model and it will give you wings.

The installation of the demo report is actually a breeze. I presume you'll be using SE80 rather than ADT. If you use ADT, you'll find it no problem to adapt the instruction below.

  1. Download all files attached to this blog post.
  2. Install them as follows:
ActionImage
Create a local class ZLOGGER. This will be our emulation of the logger wrapper implementation. In your productive application you'd use something more functional, like e.g. a BAL log wrapper proposed by Eric Petersen in his blog. Just accept default options and save it in $TMP.screenshot023.png
Switch to source-code based edytor.screenshot024.png
Copy-paste the source code from the appropriate section of the CLASSES.txt attachment to this blog and activate the class.screenshot025.png
Repeat the same operations for the class ZLOG_ASPECTscreenshot026.png
...and for the class ZDEMO_APPLICATIONscreenshot027.png
Finally, create report ZVESNA_AOP_LOGscreenshot028.png
Default options will do just fine. Confirm and save in $TMP.screenshot029.png
Copy-paste the contents of the ZVESNA_AOP_LOG.txt source code file and activate the report.screenshot030.png

 

All right, so what am I looking at?

What you have in front of you at this point is a simple AOP application, a small tribute to Mr. Masataka Taketsuru, the creator of Yoichi whisky brand, since 1940 known as Nikka. Personally, I'm not particularly fond of modern trends to die as virgin as you can, therefore I greatly appreciate the efforts of great masters of humanity to bring some colour to life. The small AOP app in front of you allows you to evaluate approximate distance in days between a chosen brand of whisky and reference brand which has been set to Yoichi, 1934 (it's just my personal taste, no philosophy behind it).

But we're here to see some nice and good logging, right? So let's get down to it.

As soon as you run the application you will see an output similar to this:

Application returned:
Yamazaki is 4018 days older than reference brand Yoichi.

 

Log output:
20.10.2014 21:30:11,5160000: Starting whisky age evaluation app...
20.10.2014 21:30:11,7510000: About to evaluate Yamazaki dated 01.01.1923.
20.10.2014 21:30:11,7510000: Evaluation result for Yamazaki: Yamazaki is 4018 days older than reference brand Yoichi.
20.10.2014 21:30:11,7510000: Whisky evaluation app finished.

Now, what's so special about it?

 

Logging AOP style

If you take a look at the actual application code of the class ZDEMO_APPLICATION you'll see no trace of logging. Nowehere. There are no traces of any logger bindings. So how come that we do have some logger entries (marked green in the listing above) somewhere right in the middle of the application?

 

The answer is AOP configuration

In the upper part of the demo app screen, when you run it, you'll see Vesna config for the application. Please take a closer look at the part marked blue:

<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.vesnaframework.org" xmlns:aop="http://www.vesnaframework.org/schema/aop">

  <bean id="application" class="ZDEMO_APPLICATION">

    <!-- Date established: -->

    <constructor-arg name="REFERENCE_DATE" value="1934-01-01" />

    <!-- Reference whisky brand: -->

    <constructor-arg name="REFERENCE_NAME" value="Yoichi" />

  </bean>

  <bean id="logAspect" class="ZLOG_ASPECT" >

    <constructor-arg name="LOGGER" ref="logger" />

  </bean>

  <aop:config autoproxy-mode="default">

    <aop:aspect ref="logAspect">

      <aop:around pointcut="execution(*)" method="PROCESS"/>

    </aop:aspect>

  </aop:config>

</beans>

What you're looking at is aspect weaving configuration, instructing our tiny Vesna app that it needs an around advice for every method call since pointcut expression is set to wildcard (*). Also, it tells Vesna framework that the advice is implemented by the method PROCESS of the bean referenced to as logAspect. If you're unfamiliar with AO terms, please consult the documentation for any aspect-enabled language. Java Spring documentation will do for that purpose.

 

How does it work?

Well, really simple, in fact. Vesna Framework uses advanced proxying mechanism that allows for runtime aspect weaving, based upon defined pointcuts. This mechanism is very similar to what is being used in other AOP-enabled evironments.

 

Ultimate separation of concerns

I might have resisted from this boisterous heading for this paragraph but it was too tempting, really... Since AOP really does give you exactly what you'd wish for your application: being able to inject the logging anywhere you'd want, without changing a single line of your code.

The logging functionality itself is encapsulated in the class ZLOG_ASPECT. Needless to say, you can use more aspects calling specialized logs for various functional contexts in your application. Logging aspect uses logger bean, encapsulating actual log wrapper of some kind.

Since our aspect is of an around kind, its signature of the logging method PROCESS must contain at least the reference to the join point /ARCONA1/PROCEEDING_JOIN_POINT. The parameter name is meaningless. This parameter allows the aspect to make a decision to pass the call further down the call chain, by the means of using the PROCEED( ) method, or not. In our logging case we don't want to interfere with application logic itself so we'll call that.

Apart from that, the signature of the ZLOG_ASPECT->PROCESS( ) method may contain also same parameters as captured method. In our case these are: DATE, NAME and RESULT. In such a way we can easily use original paremetr values of the method call at runtime, e.g. to do better logging.

 

There's more than just logging to AOP

I hope I got you interested... In Japan's whisky heritage!

But - as regards AOP - the logging is just the beginning. Do you think that changing the parameters of a method's call on-the-fly could be fun? Then stay tuned to the next part of the Vesna blog!


The small print

Needless to say, all whisky brand names used in this blog belong to their proprietary holders. The author of this blog is in no way associated with any of them. However, let the mastery of Japanese whisky creators never be forgotten, howgh.

A Collection for ABAP OO: Vesna Generic Array

$
0
0

Motivation

Who out of ABAP OO programmers is not bored to tears with endless declaring of internal tables. Firstly, decide the type: most folks use the standard, some go for sorted or hashed, always decisions, decisions. Then the key: what fields, unique, not unique, in those really rare cases where you have large amounts of data to process you may also consider a secondary key... All that not exactly in line with what usually an OO programmer would do. Take Java, .NET, AS3 or whatever OO environment you like. They all have, yes, what do they actually use if they do without such abundance of tables which are everything but OO?

 

Collections

In AS3, my favourite environment to show how simple yet brilliant OO can be, a collection can take mutliple forms: an array - a table of anything, a vector - a dense table of same objects or a dictionary where keys are subject to a strict comparison... All of that completely awkward in an ABAP OO environment. In ABAP OO terms, I'm talking double Dutch here.

 

So what? No collections in ABAP OO?

Nearly. However, if you spare a few minutes to have a look at the demo Vesna AOP application, you'll notice that the class ZLOGGER does not exactly use any kind of internal table for caching log entries. Instead, it hosts an attribute of type ref to /ARCONA1/ARRAY.

 

Generic array of stuff

/ARCONA1/ARRAY is a simple, generic collection of anything. It offers two modes: access by index or access by a key while the key is of string type. It's very, very simple.

 

Feel the simplicity

What can you store in such an array? Well, just about anything, really: a simple field, a structure, an internal table, a reference or an object. It behaves as close to any OO array as possible. In fact, /ARCONA1/ARRAY is an OO array. The best one you can have at this point. Developed, tested and improved continuously in Vesna Framework environment.

 

All right, so what is it good for?

Short answer: anything. Long version: you can use an OO array exactly in the same places where you'd be tempted to declare an internal table, with the only difference, it's OO. So you can use it like a stack or iterator:

 

Push

Add new items to the end of the array

 

Get next

Traverse the array (something like an OO loop)

 

Set by key

Insert anything into the array with a given key

 

Set by index

Insert anything into the array at specified index

 

Get with key

Retrieve an item for given key

 

Get with index

Retrieve an item for given position in the array

Other methods of the /ARCONA1/ARRAY class are of mostly internal use, like, e.g. in order to ensure its proper serialization.

 

How useful is it?

Very, very usefull. In any everyday programming context. You'll definitely notice immediately how your ABAP OO code becomes closer to a proper OO. It's unlikely that you'll be tempted to declare another internal table in your code, ever again.

I'd post some examples but I don't think it actually makes sense... All in all, if you read so far, you probably belong to this party of ABAP OO programmers who know exactly what collections are for and simply miss that functionality in NW ABAP dearly so I'm not going to bother you with things you're highly likely to already know.

 

All right, it's all nice, but how do I get it?

Vesna OO array is part of Vesna Framework. This is, however, neither the only nor the best reason to install it. Vesna gives you much more: Spring-like functionality for ABAP OO including AOP capabilities. If I got you interested, follow these links to get started:

Stay tuned to the next part of Vesna blog!

ABAP News for 7.40, SP08 - GROUP BY for Internal Tables

$
0
0

You know the GROUP BY clause from SQL. There was not such a clause for internal tables up to now. All we had was that clumsy group level processing with statements AT NEW ... that relied on the order of table columns and contents that is sorted respectively.

 

With release 7.40, SP08 there is a real GROUP BY clause for LOOP AT itab that is much more powerful than the SQL one.

 

DATA flights TYPE TABLE OF spfli WITH EMPTY KEY.

SELECT * FROM  spfli
         WHERE carrid = '...'
         INTO TABLE @flights.

 

DATA members LIKE flights.
LOOP AT flights INTO DATA(flight)
     GROUP BY ( carrier = flight-carrid cityfr = flight-cityfrom )
              ASCENDING
              ASSIGNING FIELD-SYMBOL(<group>).
  CLEAR members.
  LOOP AT GROUP <group> ASSIGNING FIELD-SYMBOL(<flight>).
    members = VALUE #( BASE members ( <flight> ) ).
  ENDLOOP.
  cl_demo_output=>write( members ).
ENDLOOP.
cl_demo_output=>display( ).

 

Looks like dreaded nested LOOPs, but it isn't quite that!  What happens here is that the first LOOP statement is executed over all internal table lines in one go and the new GROUP BY addition groups the lines. Technically, the lines are bound internally  to a group that belongs to a group key that is specified behind GROUP BY.The group key is calculated for each loop pass. And the best is, it need not be as simple as using only column values, but you can use any expressions here that normally depend on the contents of the current line, e.g. comparisons, method calls, .... The LOOP body is not evaluated in this phase!

 

Only after the grouping phase, the LOOP body is evaluated. Now a second (but not nested) loop is carried out over the groups constructed in the first phase. Inside this group loop you can access the group using e.g. the field symbol <group> that is assigned to the group in the above example. If you want to access the members of the group, you can us the new LOOP AT GROUP statement, which enables a member loop within the group loop. In the example, the members are inserted into a member table and displayed.

 

Here another example, where the group key is evaluated from method calls:

 

LOOP AT flights INTO DATA(wa)

     GROUP BY ( tz_from = get_time_zone( wa-airpfrom )

                tz_to   = get_time_zone( wa-airpto ) )

     ASSIGNING FIELD-SYMBOL(<group>).

  ...

ENDLOOP.

 

Of course, there is also expression enabled syntax for grouping internal tables.

 

In a first step, we get rid of LOOP AT GROUP by replacing it with a FOR expression:

 

DATA members LIKE flights.

LOOP AT flights INTO DATA(flight)

     GROUP BY ( carrier = flight-carrid cityfr = flight-cityfrom )

              ASCENDING

              ASSIGNING FIELD-SYMBOL(<group>).

  members = VALUE #( FOR m IN GROUP<group> ( m ) ).

  cl_demo_output=>write( members ).

ENDLOOP.

cl_demo_output=>display( ).

 

The IN GROUP is a new addition to FOR. Second, away with the outer LOOP:

 

TYPES t_flights LIKE flights.

DATA out TYPE REF TO if_demo_output.

out = REDUCE #( INIT o = cl_demo_output=>new( )

                FOR GROUPS<group> OF flight IN flights

                GROUP BY ( carrier = flight-carrid cityfr = flight-cityfrom )

                  ASCENDING

                LET members = VALUE t_flights( FOR m IN GROUP <group> ( m ) ) IN

                NEXT o = o->write( members ) ).

out->display( ).

 

FOR GROUPS is another new FOR variant. Believe me, it does the same as the variants above. But for reasons of readability, the combination of LOOP AT GROUP with a FOR IN GROUP within might be the preferable one, at least for this example .

 

For a deep dive, read this and this!

Lazy initialization in ABAP

$
0
0

"In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed." (Wikipedia)

 

A very unused yet extremely simple software design technique is the lazy initialization (sometimes referred to as lazy instantiation or lazy loading). This is exceedingly helpful in large applications where a massive amount of data must be loaded and/or calculated at runtime.

 

For a better understanding, the following ABAP scenario is taken into consideration:

A company/client needs an application to display all the information related to a single entity model. Because the amount of that cannot fit into a single database table or a single screen, a decision has been taken to implement the display in the form of a tab strip, where each of the tabs will encapsulate information in different forms with the possibility to integrate different data sources (E.g. entry/entries from the underlying or external database, calculations, aggregates, RFC calls, Web Services, etc.).

 

In this example, several database tables will be used, each will correspond to one of the tabs:

tabs and data sources.png

The database objects will be uniquely identified by a key value structure, which will be referred to as the "common key". When the application is started and the tab strip is instantiated, the only known data is:

  1. The common key
  2. ID of the first displayed tab

(For clarity purposes, each data source will be named according to the corresponding tab: D1, D2 and so on.)

 

Because the business logic must be UI-independent, the application will be structured in two packages:

  1. Business object (BO) layer – encapsulates the data model and functionality
  2. User interface (UI) layer

 

Using a bottom-up approach, the BO layer will be designed first. For each data sources (in this case: ZD1, ZD2, etc.) a corresponding business class must be created.

bo architecture.png

ZCL_FACTORY will act as a bottleneck for the creation of the subordinate objects, which can only be instantiated by the factory method.

As the factory class contains a list of already instantiated BOs, it should also be a Singleton. The factory's constructor method is optional, but it can be used for example to either enqueue existing data in Change-mode or generated the common key in Create-mode.

 

A snippet of the ZCL_FACTORY class with some explanations:


CLASS zcl_factory DEFINITION
                 
PUBLIC

                                       FINAL

                  CREATE PRIVATE.

PUBLIC SECTION.
CLASS-METHODS get_instance
  
IMPORTING
    
value(iv_common_key) TYPE guid OPTIONAL
   RETURNING
    
value(ro_factory) TYPE REF TO zcl_factory.

METHODS constructor
  
IMPORTING
    
value(iv_common_key) TYPE guid OPTIONAL.

METHODS factory
  
IMPORTING
    
value(iv_type) TYPE string
   RETURNING
    
value(ro_bo) TYPE REF TO zcl_abstract_bo.

PRIVATE SECTION.
TYPES:
  
BEGIN OF ts_list,
     classname
TYPE classname,
     bo 
TYPE REF TO zcl_abstract_bo,
  
END OF ts_list,
   tt_list
TYPE STANDARD TABLE OF ts_list.

CLASS-DATA :
   mo_factory
TYPE REF TO zcl_factory.

DATA :
   mt_list      
TYPE tt_list,
   mv_common_key
TYPE guid.
ENDCLASS.


CLASS zcl_factory IMPLEMENTATION.
METHOD constructor.
   mv_common_key
= iv_common_key.
ENDMETHOD.

METHOD factory.
  
DATA :
     lv_classname
TYPE classname.

FIELD-SYMBOLS :
   <fs_list>
TYPE ts_list.

*   Obviously these hard-coded values are not optimal
CASE iv_type.
  
WHEN 'D1'
    
OR 'D2'
    
OR 'Dx'.
       lv_classname
= |ZCL_BO_{ iv_type }|.
  
WHEN OTHERS.
*      RAISE EXCEPTION TYPE ...
ENDCASE.

*   Check if the list already contains an instance
READ TABLE mt_list ASSIGNING <fs_list>
                   
WITH KEY classname = lv_classname.

*   If not, create
IF NOT sy-subrc IS INITIAL.
  
APPEND INITIAL LINE TO mt_list ASSIGNING <fs_list>.
   <fs_list>
-classname = lv_classname.
  
CREATE OBJECT <fs_list>-bo TYPE (lv_classname)
    
EXPORTING
       iv_common_key
= mv_common_key.
ENDIF.

*   Return BO instance
   ro_bo
= <fs_list>-bo.
ENDMETHOD.

METHOD get_instance.
*   Singleton method to retrieve factory instance
IF mo_factory IS INITIAL.
*    Just as an example for Create/Display
  
IF iv_common_key IS SUPPLIED.
    
CREATE OBJECT mo_factory
      
EXPORTING
         iv_common_key
= iv_common_key.
  
ELSE.
    
TRY.
      
CREATE OBJECT mo_factory
        
EXPORTING
           iv_common_key
= cl_uuid_factory=>create_system_uuid( )->create_uuid_x16( ).
    
CATCH cx_uuid_error.
*        ...
    
ENDTRY.
  
ENDIF.
ENDIF.

   ro_factory
= mo_factory.
ENDMETHOD.
ENDCLASS.

 

Note: Attribute MT_LIST can also be used as a mechanism to control methods like: SAVE, CHECK_BEFORE_SAVE, HAS_CHANGES, and so on; but this depends on particular scenarios.

 

At this point, each specific BO can be implemented to match the particular use case.

  1. E.g. ZCL_BO_D1 reads a single entry from the database and displays it as a form. Therefore each field will have corresponding getter and setter methods. Alternatively, ZCL_BO_D2 will select a number of rows from the database and output them as a table. In which case, CRUD functionalities might be more adequate.

The constructor of each BO is responsible to load the data buffer using the given common key.

 

Note: As all the business objects have the property CREATE PRIVATE, each one must declare ZCL_FACTORY as friend.

 

The following statement can be used to create a BO instance for D1:


DATA:
lo_bo
TYPE REF TOzcl_bo_d1.

lo_bo ?= zcl_factory
=>get_instance( )->factory( 'D1' ).


After the business logic is active and secured, it is time to move up towards the UI layer. For this example, the user interface has been implemented both as an ABAP report and a Web Dynpro application. Nevertheless any other UI technology can be used.


1. ABAP Report

The most elementary implementation requires a main screen (100) and two sub screens (101, 102). The latter are embedded into a tab strip control belonging to the main screen. The trick here consists of adding the BO instantiation in the PBO module of each sub screen. As the PAI module of screen 100 controls the tab strip actions, the corresponding PBO modules are only called upon when necessary. This means that data is only loaded when displayed.

 

2. Web Dynpro Application

The application consists of a main WD component with a start view and an embedded TabStrip UI element. Based on the complexity of the application, it is a matter of choice how each tab is implemented:

     2.1. Directly in the same view

     2.2. As a different view inside the same application

     2.3. As a separate WD component

 

Either way, the component controller (from the main component 2.1., 2.2., or the each used component, 2.3.) must implement initialization method(s) – for 2.3., these methods must be defined as interface.

The catch in this situation is that TabStrip UI element has an event called ON_SELECT. For this event, an associated event handler is implemented in the start view of the main component. Similar to the PAI module, this method is used to determine the navigation and therefore control the BO instantiation.

 

METHOD onactionon_select.
 
CASE wdevent->get_string( 'TAB' ).
   
WHEN 'D1'.
   
WHEN 'D2'.
*     2.1., 2.2.
      wd_comp_controller
->init_d2( ).
*     OR

*     2.3.
      wd_this
->wd_cpifc_d2( )->init( ).
   
WHEN 'Dx'.
 
ENDCASE.
ENDMETHOD.

 

Note: This can also be implemented using Floorplan Manager (FPM) as an OIF component by checking the navigated tab in method PROCESS_BEFORE_OUTPUT.

 

Evidently, it is important to set the most used tab as initial or give the possibility for the user to choose.

 

In the end, this is the most rudimentary example I could think of, but it can nevertheless be scaled tremendously.

 

 

Thank you and please feel free to contribute. My only hope is that I didn't compress the content to the extent that it is not understandable.

 

Tudor


Australian SAP User Group Conference 2014

$
0
0

SAP Australia User Group Conference 2014 – Hilton Hotel, Sydney

 

image001.jpg

 

One thing that Australia has in abundance, apart from deserts and deadly wildlife, is SAP conferences. I was lucky enough to be presenting at the Australian SAP User Group conference in Sydney the other week, and I thought I would share some of the content from this event with you. In the past I have moaned and groaned and waffled on for ages about my dislike for blogs which purport to talk about SAP conference but which in reality talk about the food, and show pictures of dustbins, and list all the exciting cool people that the author met. Naturally this blog is going to be nothing like that.

 

Monday 8th of September

 

Upon arrival at the conference the first thing one’s eyes are drawn to is the exceptional quality of the dustbins. Set in a stunning silver style, with a crisp black bin bag, these beauties are capable of going from zero to sixty miles an hour in four seconds, if you were to throw one off a cliff.

 

Breakfast

 

To kick off the day we are served pigeon with warm foie gras, foie gras sorbet, beetroot, cocoa beans with a protruding pigeon leg immersed in Banyuls sauce. The unique pigeon taste and flavor blends well with the silken foie gras. For after’s we have a doughnut. This lavish fried treat is filled with Dom Perignon champagne jelly, and is topped with a 24-carat gold leaf, white chocolate flowers dusted in gold and edible diamonds.

 

International SAP Executive Update – Paul Young, GVP Customer Strategy, SAP AG

 

After having assorted top ten singles in the eighties such as “Love of the Common People” Paul Young then went on to become a high ranking member of software company SAP and became Scottish also. In this talk he brought to our attention that SAP have a product called HANA. To be serious for a second the main message here, which was to be repeated throughout the conference was that just doing the same thing as before really fast, whilst good, is not what HANA is all about. The point is to try and do things that you could not do before because they were in the “too hard” basket.

One interesting – and horrifying – theme that kept coming up throughout this conference is about how big companies want to get as much information about you as possible. The example given here was Disney theme parks where you buy some sort of wrist bracelet and if you wear it you get assorted benefits but in return the Disney corporation track you in real time and analyse everywhere you go and everything you buy, how long you stand in queues for certain rides etc.. A full scale 1984 type of thing and people are willing to pay to have this done to them.

The aim of the so called “big data” then seems to be to (a) predict what someone is going to do next with an aim to making money out of them and the next stage would be (b) to influence/control what someone is going to do next with the aim of making money out of them.

 

Next cab off the rank was Ray Wang, founder of Constellation Research. The previous keynote was naturally SAP focused, Ray talked in much broader terms about where technology is taking the world.

 

Morning Tea

 

To calm us down after the keynote speeches out comes an eel dish that reflects the so-called evolution technique, where the fish is cooked in two ways: as a slow-cooked technique requiring six and a half hours at 65 degrees, and the convention grilling. The dish is served with herbs, garlic and reduction sauce of eel juices and citrus, with potatoes coated with pepper powder on the side, and pan fried kangaroo loins.

There were a large number of SAP mentors in attendance at this conference, such as Graham Robinson, Jocelyn Dart, Professor Paul Hawking, Tony de Thomasis, and Greedy Smith from the pop group “Mentor as Anything”. Morning tea is a good opportunity to swap business cards with them and talk about HANA and UI5.

 

Next was a forty minute advert for IBM disguised as a keynote speech. The good thing about SAP conferences these days is that there is very little of this now, it used to be almost every speech was an advert at SAPPHIRE type events.

 

Then it was breakout time where you decide what you want to see. There were no less than five tracks, so you were spoilt for choice – you can always tell when a conference is going to be good when it is difficult to decide which presentation you want to see. I plumped for solution manager to start off with, and David Noack from SAP talked about how to best manage two major releases a year. I cannot talk for other companies, but where I work we put changes into production every week, so change management is more of an ongoing process than managing two great big big bangs each year.

 

Lunch

 

image002.png

 

The first day’s lunch consists of a sensational beef dish that comes from a 7-year-old dairy cow, which is slaughtered in front of our eyes and then cooked right on a table in the middle of the exhibitor hall on a hot stone. Once done, it is served with potato crisps, mushrooms and buttery bone marrow, with an accompaniment of tandoori crocodile, all washed down with port which has been guarded by eunuchs on top of a mountain in deepest Transylvania for 100 years.

 

I am a big fan of BRF+ so next I went to see Jocelyn Dart talk about why SAP has felt the need to have no less than three different business rules engines, and which one should you use. SAP is always doing this sort of thing, offering you multiple ways to achieve the same thing. In this case we have the ABAP based BRF+ which started life in Business One and is now part of the ECC 6.0 system, we have a Java based equivalent which uses technology acquired by SAP and naturally there is a HANA rules engine as well.

 

Then came what was for me the highlight of the conference which was Graham Robinson doing a session on UI5. He had no slides at all, he spent the whole time coding live, as he changed the code you saw what the result was in the UI5 application being played with. UI5  is not as scary as all that, once you get over the fact that you have to program the front end in JavaScript (a concept which makes traditional ABAP people shake with fear) things become a lot more straightforward.

 

Afternoon Tea

 

To complement the bowls of sweets we have chocolate made from Venezuela's rare Porcelana Criollo bean, topped with Tahitian Gold Vanilla Caviar and edible gold flakes together with vegemite on toast. Also we have Louis XIII de Remy Martin Cognac which comes in a hand blown sugar Fleur-de-Lis.

There were a large number of fictional characters from eth middle ages in attendance at this conference, such as Bill Brewer, Jan Stewer, Peter Gurney, Peter Davy, Dan'l Whiddon, Harry Hawke, Old Uncle Tom Cobley and all.Afternoon tea is a good opportunity to swap business cards with them and talk about HANA and UI5.

 

Then it was my turn to wow the audience with a talk on “secret” things you never knew were inside your SAP system. SAP used to have a split between new functionality delivered via enhancement packs, and bug fixes delivered via support stacks. Recently this has changed such that enhancements packs only come out every two years instead of annually, but in the meantime new functionality gets sneaked in via support stacks. Two examples are the ABAP Test Cockpit which came along as part of a support stack, and every support pack adds more tests to the code inspector, and the BOPF (Business Object Processing Framework) which is a major chunk of functionality which arrived via support stacks are opposed to being part of an enhancement pack.

 

To end the day we have another keynote, this time by David Roberts who is a top dog accountant at USA Company “Under Armour”. They have all former sports stars working for them, and so they do not have meetings they have “huddles”. How they work is to start of someone shouts out “Will you protect this house?” and everyone has to shout “I Will!” at the top of their voice. Then someone else shouts out “How much do you want it?” and the correct response is “I want it so much, I want t more than I want to breathe”. And this is the accountants. I shudder to think what sales and marketing do in their meeting equivalents.

 

Network Drinks

 

image003.png

 

To wash down the glasses of Henri Jayer Richebourg Grand Cru wine from Cote de Nuits in France are some fresh lobsters with select shellfish in summer vegetables, heads of fresh bulbs mixed with herbs in bubbly, light vinaigrette and a meat pie.This meat pie contains Wagyu beef fillet, Chinese matsutake mushrooms, winter black truffles, and French bluefoot mushrooms. Two bottles of vintage 1982 Chateau Mouton Rothschild wine are used in the gravy and the crust is covered in edible gold leaf.

 

Tuesday 9th

 

Breakfast

 

Todays breakfast includes bacon from rare pig breeds, truffle, watercress, saffron and an egg all cooked in truffle oil, sprinkled with real gold dust and served between a bun, along with caviar and a selection Louis Roderer Cristal Brut 2000 champagne sherbet and Madagascar chocolate cake with Moët très fine Champagne No. 7. The breakfast included a croissant covered in edible gold and jewels, Bar le Duc hand-seeded redcurrant jam, Kopi Luwak coffee, and a champagne and Chambord cocktail. All this was served from a bottle covered in gold and encrusted with real pearls and diamonds.

 

After that we staggered into the auditorium to hear the first of two keynotes, starting off with Alan Capes from the Canadian National Railways. That organisation is a gigantic success story, moving from almost going down the gurgler to becoming one of the most profitable railways companies in the world, and a large part of this is attributed to use of IT systems i.e. SAP.

 

Then we had a non SAP related keynote, Professor Hugh Durrant-Whyte from the Australian ICTA Research Centre of Excellence talked about how to use the nebulous concept of “big data” to actually make a difference in the real world – one example was the mapping that was ben done (somehow) of the entire layout of Australia many kilometers under the surface. What is being looked for are rocks that glow naturally hot, so a hole can be drilled and the heat transformed into renewable power. The same principle is naturally even more important to mining companies

 

Morning Tea

 

Fresh langoustines served on the SAP booth table alive, and “seared’ with a knife 15 minutes before the delegate devours it, which is a style that’s beyond a guarantee of freshness.

 

There were a large number of Hollywood movie stars in attendance at this conference, such as Brad Pitt, Matt Damon, Julia Roberts, George Clooney, Harrison Ford and Betty Boop. Morning tea is a good opportunity to swap business cards with them and talk about HANA and UI5.

 

Then there was one of the best attended sessions of the conference, in which Simon Kemp talked about and demonstrated the “Fiori Launchpad” which is new and shiny and everyone liked the look of it. I might be burnt at the stake for saying this, but this is an evolution of the “user menu” concept which has been around a long time in SAP, this time you customize lots of boxes all over the initial screen, each of which launches a fancy UI5 transaction (or something else). I feel sorry for anyone demonstrating this, as they keep getting asked the “is this the end of the SAP portal?” question, along with “is this the end of ESS/MSS?”. No-one wants to answer that question, but if I were a life assurance salesman the the SAP Portal came to me as a customer I would think twice.

 

Lunch

 

image004.png

 

A crunchy-tender-juicy-heady suckling pig served with tomato balls or “bolao” and pools of tomato jelly, with confit garlic to decorate the plate, and a crunchy funnel web spider sauce.

 

The former Prime Minister of Australia, said last year the Australian mining boom is over, but if it is no-one has told mining company Fortescue Metals. The CIO of that company, Vito Forte, gave a keynote speech, starting off with the growth figures for the company over the last few years, which is quite startling. Some of my colleagues went to Western Australia last year and showed me photographs of the sea being filled with ships, all waiting for the tide to change so they could take that days output to China or India or wherever. Fortescue metals is clearly a company which takes advantage of the latest SAP innovations, and the CIO talked about making sure the IT department is not the “department of no”.

 

The next keynote was from the CIO of Fairfax Media, a company which is being forced to reinvent itself for the digital age, as traditional media sectors like printed newspapers go into terminal decline. He showed a chart of some recent research which suggested that just 4% of people looked at adverts in printed newspapers, and yet companies still spend 18% pf their advertising budget on such things. He is all too horribly aware that this is just because “we have always done it this way” and one day companies will wake up.

 

Afternoon Tea

 

The final meal of the day is Duck Consommé served with what they call corn silk, with chocolate, vanilla purée, rice and apple, and deep fried emu in a beer batter.

 

There were a large number of rock starts in attendance at this conference such as Jimmi Hendrix, Freddie Mercury, Michael Jackson, John Lennon and Buddy Holly. Afternoon tea is a good opportunity to swap business cards with them and talk about HANA and UI5.

 

SAP Mentor Tony de Thomasis talked about the various tools available to you when preparing for an SAP upgrade. He is not a big fan of “technical” upgrades, and subscribes to the view that you should take advantage of new features as soon as they become available, a message that was repeated by the various CIOs of forward looking companies who spoke at this conference.

This was a very hands on type of presentation, with live demonstrations as opposed to power point slides. I noticed when an error message popped up it referred to SAP GUI version 740, which I did not think was out yet, and he considered showing  us the version 5 of the NWBC but decided against it as it is still too flaky. As it turns out these will be released on 8th of October 2015.

 

The final talk of the day was from Katrin Pietsch from SAP talking about the “customer connection program”. SAP provide many free services to their customers, the general idea is that if there is a piece of functionality that is not present in standard SAP then if you band together in a group (like a user group) then chances are you can get SAP to add it to the standard product. As an example think of all the “repairs” you make to the standard system – if a large number of companies are making the exact same change then why not tell SAP. An example I can think of is the ERS transaction MRRL. The transaction date defaults to todays date, which is crazy, so I have seen a large number of companies  make a “repair” to the standard transaction so you can specify the transaction date. Instead of five hundred companies making the same modification and then having to go through the SPAU pain at upgrade time, why not tell SAP and see if they can’t add that field as standard?

 

To end the conference we had a foot long bratwurst infused with hundred-year-old Louis XIII cognac and topped with fresh lobster, picante sauce and Kobe beef seared in olive and truffle oil, washed down with the world's oldest cocktail, created with 1788 Clos de Griffier Vieux Cognac, 1770 Kummel Liqueur, 1860 Dubb Orange Curacao and early 20th century Angostura Bitters.

 

All in all a wonderful conference, packed with fascinating SAP demonstrations, good food, and excellent dustbins.

 

Cheersy Cheers

 

Paul

 

Multi level Employee Hierarchy Report in Tree Format (Top- To-Down)

$
0
0

Hi All,

recently i got a scenario to biuld a Multilevel Employee Hierarchy report, i posted it on SCN because i was not getting how could i achieve it through custom program (There are some function modules available for the same purpose e.g. RH_STRUC_GET, but alone it was not fulfilling my requirements). Although it is something like as in standard transaction PPOME, but what i was expecting  is something different from what you can see in PPOME transaction. After posted the query on SCN , i was not able to get a single reply (strange for me , i don't know why). Then i decided to create a Custom Program to show Multilevel Hierarchy Report for Employees, in which you can see all those employee under any level along with its designation , Name, its id, and so on. I have hided the name of Concerned person in this screenshot, and anyone can edit this program to make a good use of Custom Multilevel Hierarchy report.

Although i have searched for the same on SCN, but i got all the answer which was related to the Hierarchy of one person. And it was not my requirement. So, here i am posting this whole code alongwith the screenshot of Output, so that it will benifit all those members or new persons who wants to create a Multilevel Hierarchy Report.

(There may be some correction in this program, which might help in creating a more benificial list, i will appreciate all those suggestions which will come to me to add within my custom code.)

 

Employee Hierarchy.PNG

 

 

In the above screenshot i have shown that how many peoples are there under each level, The Source Code can be optimised for any data related to this Hierarchy (Means you can add your needy data to show here.).

 

 

Regards

Sanjeev kumar.

Static ABAP Code Analysis using ConQAT (and SCI)

$
0
0

 

Introduction

 

Why an additional tool for static code analysis?

With the Code Inspector (SCI) and the ABAP Test Cockpit (ATC) SAP already provides powerful tools for the static code analysis. We are using these tools (especially SCI) already for years, but there are some usability and functionality gaps which can be closed using ConQAT. Examples for that gaps are:

  • Usable visualization of results (with text and graphics).
  • Baseline mechanism (define a code baseline for which no remarks are reported, e.g. in case of maintenance projects).
  • Historical view on check results (how the code quality increases/decreases over the time).
  • Check for redundant coding.

 

What is ConQAT?

ConQAT (Continuous Quality Assessment Toolkit) is a software quality analysis engine which can be freely configured cause of using the pipes and filters architecture. For a detailed description have a look to ConQAT - Wikipedia. Some key points I wanna take out are:

  • Configuration of analysis via Eclipse (using an Eclipse plugin).
  • Support of different languages (e.g. Java, C/C++/C#, ABAP). Due to the flexible architecture of the scan engine it can be enhanced for any language. So also for example SQLScript, which comes more and more in the focus for us.
  • Integration of results from other tools (e.g. SCI, FindBug).

 

How is ConQAT used in our ABAP projects?

In our ABAP projects ConQAT is used in the following way:

  • It is configured to analyze the coding two times a day. This means that the coding of the to be analyzed packages is extracted and analyzed by the ConQAT engine. This process also starts a configured SCI variant. The results of the SCI run are also extracted and considered by ConQAT. From my point of view I would prefer a higher frequency of analysis runs, but at the moment this is not possible within our landscape. In the future this problem will be solved by the successor of ConQAT (but more on that in the Outlook section).
  • The results of ConQAT (with the integrated SCI results) are provided as a HTML Dashboard. On the dashboard an overview section gives a first insight to the results. Within the specific sections different detailed data regarding the analysis can be found. In the dashboard the developer can navigate also down to code level (displayed in the browser) where the remarks are marked at line level. Via an integration of the ADT Links the developer can directly jump out of the dashboard to the coding in Eclipse to edit it.

 

ConQAT General Information

ConQAT provides the following general information in the result output. In the following chapters I show just the graphical output of a demo analysis, but of course there is also a text output for the objects for which remarks exist.

 

Overview

The overview page gives an overview about the metrics. It displays how many remarks we have in the whole system and it displays how many remarks we have in the delta to a defined baseline.

01_general_information__overview.png

 

Architecture Specification

With ConQAT it is possible to define an architecture specification. It describes which objects can be used by which other objects (e.g. so it can be defined, that the UI layer cannot directly use objects from the data access layer). The relationships can be defined from package level down to single object level. From an ABAP point of view this than be compared to the ABAP package interfaces. The following figure displays a specification which defines the relationships on package level.

01b_architecture_specification.png

 

Treemap Outline

The Treemap Outline gives displays the analyzed ABAP packages. If the developer hovers with the mouse over a package he gets more information about e.g. the package size (lines of code).

02_general_information__treemap_outline.png

 

System Size Trend

On the System Size Trend page it can be identifed how the system size grows over time. It is also visible how many lines of code are generated and how many are coded manually (generated objects can be marked in the configuration).

 

LoC = All Lines of Code (manual, generated, comments)

SLOC = Manual Lines of Code without comment lines

LoCM = Manual Lines of Code with comment lines

LoCG = Generated Lines of Code

03_general_information__system_size_trend_01.png

03_general_information__system_size_trend_02.png

 

Modified Source

The modified source code is also visualized using treemaps. So in an easy way it can be found out where the changes were done in the system (added/changed/removed coding).

01_modified_source.png

 

Task Tags

ConQAT also can be configured to report task tags (e.g. TODO, FIXME).

05_general_information__task_tags.png

 

ConQAT Code Metrics

 

Architecture Violations

Violations of the defined architecture (see section above) are displayed in the same graphical way as the architecture specification itself. In addition to the "green" arrows displaying the allowed relations, violations are displayed as "red" arrows.

 

Clone Coverage

ConQAT analyzes clones within the coding. This is not just a search for exactly the same code parts. The algorithm considers same code structures.

This check helps to detect coding which can be encapsulated in reusable functionalities and it helps also to detect "copy & paste" coding which will lead in most cases to error situations when in later versions not all places are adjusted (because of e.g. a defect, an enhancement). From a Clean Code Development perspective it helps to avoid violations of the "Don't Repeat Yourself" (DRY) principle.


In case the information provided in the dashboard is not enough (even not on code level), ConQAT allows to compare clones with the help of an Eclipse plugin in detail.

 

01a_clone_coverage.png

01b_clone_coverage.png

 

Long Programs

ConQAT allows to check for "long programs"; classes, programs, ... which have more lines of code than defined in the configuration. To long classes for example are in most cases an evidence that the Single Responsibility principle is violated.

As in the following figure can be seen, it was configured that e.g. classes up to 600 lines of code are ok (green). Objects with up to 1500 lines of code have to be checked (yellow). More than 1500 lines of code are not ok.

For "lines of code metrics" (like Long Programs and Long Procedures as described in next section) it can be configured if comment lines are considered or not (by default they are excluded). Empty lines are ignored in general.

02_long_programs.png

 

Long Procedures

The long procedures metric checks methods, functions, ... regarding their lines of code length. Violations for that metric gives us an evidence that to much is done in e.g. one method which has to be extracted in more granular reusable code blocks. The following configuration defines that up to 60 lines of code are ok, up to 150 lines the object has to be checked. All objects with more than 150 lines of code are not ok.

 

02_long_procedures.png

 

Deep Nesting

Deep nesting is a classical metric which is also checked by ConQAT. Coding is identified which will be to complex to read and to understand because of very deep nestings.

 

Our configuration allows up to 5 deep nesting levels (which is already a high number). Up to 7 it the coding has to be checked. More than 7 it is not allowed.

 

03_deep_nesting.png

 

integrated SCI results

As mentioned before, ConQAT allows to integrate the results of SCI check runs. It can be defined which check results are marked as critical warnings or as guideline violations. The integration of the SCI results in the ConQAT Dashboard has the advantage, that not several different places have to be checked for remarks and that the results are also provided in a graphical way which gives a better overview. And of course we see directly what has been changed over time.

 

Further features

In the previous chapters I gave a general overview about the ConQAT features at a high level. The following features were partly already mentioned in these chapters, but I wanna make some further explanations to them to turn out these functionalities.

 

Baseline Mechanism

ConQAT supports code baselines. That means that you can define a code baseline for which no remarks should be reported in a delta comparsion.

 

Depending on your project following quality goals are possible:

  • No remarks: No remarks in general. That can be applied for new projects, were you start from scratch. But in case a maintenance project is taken over in most cases that quality goal cannot be applied, because the problems are integrated to deep in the system which would lead to additional implementation and tests effort if the problems should be solved (and as we all know, no one wants to pay for such things).
  • No new remarks in changed objects: In changed objects no new/additional remarks are introduced.
  • No remarks in changed objects: In changed objects no new/additional remarks are introduced and all existing remarks are solved.

 

Regarding the quality goals "No new remarks in changed objects" and "No remarks in changed objects" the baseline definition helps us to compare what was already there and what is new.

 

ConQAT analyzes the complete coding, reports the remarks for the whole system, but returns also just the delta compared to the baseline (if configured).

 

 

Detailed code analysis in browser

In the HTML Dashboard the developer can navigate down to code level. On a single object level he sees all remarks for the object on the top. When he scrolls through the coding he sees the remarks also by a marker on the left side. So without entering the system, the problems can already be analyzed in detail.

 

01a_code.png

01b_code.png

 

Integration with ABAP in Eclipse

With the ADT Tools so called ADT Links were introduced. Links which can open ABAP objects directly in Eclipse. This ADT Link feature is integrated in the dashboard. So a developer does not need to copy & paste the object name if he wants to edit it. He just has to click on the link to open the object directly in Eclipse ready for editing.

02_adt.png

 

Blacklisting

Not every remark of ConQAT must be a valid remark (cause of different reasons). For that ConQAT supports blacklisting of remarks, so that the remarks are ignored in the further analysis runs.

 

Conclusion & Outlook

As you have seen, ConQAT is a powerful tool for static code analysis which gives a better overview over the systems code quality. With the integration of the SCI results you have the option to define one single place where all check results can be found and analyzed. Due to the flexible architecture ConQAT allows also that further languages can be analyzed which are in focus in the SAP development context (e.g. SQLScript or JavaScript).

At the moment the only thing I do not really like is that the code analysis only runs twice a day due to our configuration. But this problem will be solved with the successor of ConQAT which is called Teamscale. Teamscale uses the ConQAT scan engine, but supports incremental analysis which gives us the results nearly in real-time. With Teamscale also a modern HTML5 dashboard will be delivered, which can be configured completely free by each developer, depending on its own needs.

 

Finally I can say, that our code quality has made a big step forward since we are using ConQAT.

Make your own SE16N with "Client-dependent" selection

$
0
0

hi,


There are many  excellent features when using SE16N.

 

Take a look at this thread http://scn.sap.com/community/abap/blog/2014/08/08/do-you-know-your-se16n

 

But there are also many "nice" hidden functionalities within SE16N that you can not see if you do not have the right authorisation or SAP don't want you to see/use.

 

But there is a easy way to make these features visible by making a copy of the function group SE16N to your own.

 

After copying the function group SE16N you can modify the code in the include: XXX_SE16NO01 (my called LZN_SE16NO01).

 

To make "Client-dependent selection" visible

 

Replace this code with the below code:

 

*.if not client dependent, do not bother user with client choose

*** Comment this code block
*  if gd-clnt <> true or
*     gd-no_clnt_anymore = true or
*     gd-no_clnt_auth = true.
*     loop at screen.
*        if screen-group4 = 'CLT'.
*           screen-invisible = 1.
*           screen-input     = 0.
*           modify screen.
*        endif.
*     endloop.
*  endif.

*** And replace with this one
  if gd-clnt ne true.
     loop at screen.
        if screen-group4 = 'CLT'.
           screen-invisible = 1.
           screen-input     = 0.
           modify screen.
        endif.
     endloop.
  endif.

 

Make the "Maintain entries" visible


Just comment this code block.


*.if table is editable, allow to switch it off

  "if gd-tabedit <> true.
   "  loop at screen.
   "     if screen-group4 = 'EDT'.
*          screen-invisible = 1.
   "        screen-input     = 0.
   "       modify screen.
   "     endif.
   "  endloop.
  "endif.


Step-by-step.

 

1. Start trans. SE80 and type i the function group SE16N

       Make af copy of function group SE16N to your own like ZXXX_SE16N

 

2. Modify the include  XXX_SE16NO01

3. Create a new ABAP  program and call the function module you have copied.

4. Create atransaction code ZN and call the program.


You can make your own transaction code like "ZN" og "YN" then call the function module you have just copied.

 

Please find the attached document to see in more details.



Australian SAP User Group Conference 2014

$
0
0

SAP Australia User Group Conference 2014 – Hilton Hotel, Sydney

 

image001.jpg

 

One thing that Australia has in abundance, apart from deserts and deadly wildlife, is SAP conferences. I was lucky enough to be presenting at the Australian SAP User Group conference in Sydney the other week, and I thought I would share some of the content from this event with you. In the past I have moaned and groaned and waffled on for ages about my dislike for blogs which purport to talk about SAP conference but which in reality talk about the food, and show pictures of dustbins, and list all the exciting cool people that the author met. Naturally this blog is going to be nothing like that.

 

Monday 8th of September

 

Upon arrival at the conference the first thing one’s eyes are drawn to is the exceptional quality of the dustbins. Set in a stunning silver style, with a crisp black bin bag, these beauties are capable of going from zero to sixty miles an hour in four seconds, if you were to throw one off a cliff.

 

Breakfast

 

To kick off the day we are served pigeon with warm foie gras, foie gras sorbet, beetroot, cocoa beans with a protruding pigeon leg immersed in Banyuls sauce. The unique pigeon taste and flavor blends well with the silken foie gras. For after’s we have a doughnut. This lavish fried treat is filled with Dom Perignon champagne jelly, and is topped with a 24-carat gold leaf, white chocolate flowers dusted in gold and edible diamonds.

 

International SAP Executive Update – Paul Young, GVP Customer Strategy, SAP AG

 

After having assorted top ten singles in the eighties such as “Love of the Common People” Paul Young then went on to become a high ranking member of software company SAP and became Scottish also. In this talk he brought to our attention that SAP have a product called HANA. To be serious for a second the main message here, which was to be repeated throughout the conference was that just doing the same thing as before really fast, whilst good, is not what HANA is all about. The point is to try and do things that you could not do before because they were in the “too hard” basket.

One interesting – and horrifying – theme that kept coming up throughout this conference is about how big companies want to get as much information about you as possible. The example given here was Disney theme parks where you buy some sort of wrist bracelet and if you wear it you get assorted benefits but in return the Disney corporation track you in real time and analyse everywhere you go and everything you buy, how long you stand in queues for certain rides etc.. A full scale 1984 type of thing and people are willing to pay to have this done to them.

The aim of the so called “big data” then seems to be to (a) predict what someone is going to do next with an aim to making money out of them and the next stage would be (b) to influence/control what someone is going to do next with the aim of making money out of them.

 

Next cab off the rank was Ray Wang, founder of Constellation Research. The previous keynote was naturally SAP focused, Ray talked in much broader terms about where technology is taking the world.

 

Morning Tea

 

To calm us down after the keynote speeches out comes an eel dish that reflects the so-called evolution technique, where the fish is cooked in two ways: as a slow-cooked technique requiring six and a half hours at 65 degrees, and the convention grilling. The dish is served with herbs, garlic and reduction sauce of eel juices and citrus, with potatoes coated with pepper powder on the side, and pan fried kangaroo loins.

There were a large number of SAP mentors in attendance at this conference, such as Graham Robinson, Jocelyn Dart, Professor Paul Hawking, Tony de Thomasis, and Greedy Smith from the pop group “Mentor as Anything”. Morning tea is a good opportunity to swap business cards with them and talk about HANA and UI5.

 

Next was a forty minute advert for IBM disguised as a keynote speech. The good thing about SAP conferences these days is that there is very little of this now, it used to be almost every speech was an advert at SAPPHIRE type events.

 

Then it was breakout time where you decide what you want to see. There were no less than five tracks, so you were spoilt for choice – you can always tell when a conference is going to be good when it is difficult to decide which presentation you want to see. I plumped for solution manager to start off with, and David Noack from SAP talked about how to best manage two major releases a year. I cannot talk for other companies, but where I work we put changes into production every week, so change management is more of an ongoing process than managing two great big big bangs each year.

 

Lunch

 

image002.png

 

The first day’s lunch consists of a sensational beef dish that comes from a 7-year-old dairy cow, which is slaughtered in front of our eyes and then cooked right on a table in the middle of the exhibitor hall on a hot stone. Once done, it is served with potato crisps, mushrooms and buttery bone marrow, with an accompaniment of tandoori crocodile, all washed down with port which has been guarded by eunuchs on top of a mountain in deepest Transylvania for 100 years.

 

I am a big fan of BRF+ so next I went to see Jocelyn Dart talk about why SAP has felt the need to have no less than three different business rules engines, and which one should you use. SAP is always doing this sort of thing, offering you multiple ways to achieve the same thing. In this case we have the ABAP based BRF+ which started life in Business One and is now part of the ECC 6.0 system, we have a Java based equivalent which uses technology acquired by SAP and naturally there is a HANA rules engine as well.

 

Then came what was for me the highlight of the conference which was Graham Robinson doing a session on UI5. He had no slides at all, he spent the whole time coding live, as he changed the code you saw what the result was in the UI5 application being played with. UI5  is not as scary as all that, once you get over the fact that you have to program the front end in JavaScript (a concept which makes traditional ABAP people shake with fear) things become a lot more straightforward.

 

Afternoon Tea

 

To complement the bowls of sweets we have chocolate made from Venezuela's rare Porcelana Criollo bean, topped with Tahitian Gold Vanilla Caviar and edible gold flakes together with vegemite on toast. Also we have Louis XIII de Remy Martin Cognac which comes in a hand blown sugar Fleur-de-Lis.

There were a large number of fictional characters from eth middle ages in attendance at this conference, such as Bill Brewer, Jan Stewer, Peter Gurney, Peter Davy, Dan'l Whiddon, Harry Hawke, Old Uncle Tom Cobley and all.Afternoon tea is a good opportunity to swap business cards with them and talk about HANA and UI5.

 

Then it was my turn to wow the audience with a talk on “secret” things you never knew were inside your SAP system. SAP used to have a split between new functionality delivered via enhancement packs, and bug fixes delivered via support stacks. Recently this has changed such that enhancements packs only come out every two years instead of annually, but in the meantime new functionality gets sneaked in via support stacks. Two examples are the ABAP Test Cockpit which came along as part of a support stack, and every support pack adds more tests to the code inspector, and the BOPF (Business Object Processing Framework) which is a major chunk of functionality which arrived via support stacks are opposed to being part of an enhancement pack.

 

To end the day we have another keynote, this time by David Roberts who is a top dog accountant at USA Company “Under Armour”. They have all former sports stars working for them, and so they do not have meetings they have “huddles”. How they work is to start of someone shouts out “Will you protect this house?” and everyone has to shout “I Will!” at the top of their voice. Then someone else shouts out “How much do you want it?” and the correct response is “I want it so much, I want t more than I want to breathe”. And this is the accountants. I shudder to think what sales and marketing do in their meeting equivalents.

 

Network Drinks

 

image003.png

 

To wash down the glasses of Henri Jayer Richebourg Grand Cru wine from Cote de Nuits in France are some fresh lobsters with select shellfish in summer vegetables, heads of fresh bulbs mixed with herbs in bubbly, light vinaigrette and a meat pie.This meat pie contains Wagyu beef fillet, Chinese matsutake mushrooms, winter black truffles, and French bluefoot mushrooms. Two bottles of vintage 1982 Chateau Mouton Rothschild wine are used in the gravy and the crust is covered in edible gold leaf.

 

Tuesday 9th

 

Breakfast

 

Todays breakfast includes bacon from rare pig breeds, truffle, watercress, saffron and an egg all cooked in truffle oil, sprinkled with real gold dust and served between a bun, along with caviar and a selection Louis Roderer Cristal Brut 2000 champagne sherbet and Madagascar chocolate cake with Moët très fine Champagne No. 7. The breakfast included a croissant covered in edible gold and jewels, Bar le Duc hand-seeded redcurrant jam, Kopi Luwak coffee, and a champagne and Chambord cocktail. All this was served from a bottle covered in gold and encrusted with real pearls and diamonds.

 

After that we staggered into the auditorium to hear the first of two keynotes, starting off with Alan Capes from the Canadian National Railways. That organisation is a gigantic success story, moving from almost going down the gurgler to becoming one of the most profitable railways companies in the world, and a large part of this is attributed to use of IT systems i.e. SAP.

 

Then we had a non SAP related keynote, Professor Hugh Durrant-Whyte from the Australian ICTA Research Centre of Excellence talked about how to use the nebulous concept of “big data” to actually make a difference in the real world – one example was the mapping that was ben done (somehow) of the entire layout of Australia many kilometers under the surface. What is being looked for are rocks that glow naturally hot, so a hole can be drilled and the heat transformed into renewable power. The same principle is naturally even more important to mining companies

 

Morning Tea

 

Fresh langoustines served on the SAP booth table alive, and “seared’ with a knife 15 minutes before the delegate devours it, which is a style that’s beyond a guarantee of freshness.

 

There were a large number of Hollywood movie stars in attendance at this conference, such as Brad Pitt, Matt Damon, Julia Roberts, George Clooney, Harrison Ford and Betty Boop. Morning tea is a good opportunity to swap business cards with them and talk about HANA and UI5.

 

Then there was one of the best attended sessions of the conference, in which Simon Kemp talked about and demonstrated the “Fiori Launchpad” which is new and shiny and everyone liked the look of it. I might be burnt at the stake for saying this, but this is an evolution of the “user menu” concept which has been around a long time in SAP, this time you customize lots of boxes all over the initial screen, each of which launches a fancy UI5 transaction (or something else). I feel sorry for anyone demonstrating this, as they keep getting asked the “is this the end of the SAP portal?” question, along with “is this the end of ESS/MSS?”. No-one wants to answer that question, but if I were a life assurance salesman the the SAP Portal came to me as a customer I would think twice.

 

Lunch

 

image004.png

 

A crunchy-tender-juicy-heady suckling pig served with tomato balls or “bolao” and pools of tomato jelly, with confit garlic to decorate the plate, and a crunchy funnel web spider sauce.

 

The former Prime Minister of Australia, said last year the Australian mining boom is over, but if it is no-one has told mining company Fortescue Metals. The CIO of that company, Vito Forte, gave a keynote speech, starting off with the growth figures for the company over the last few years, which is quite startling. Some of my colleagues went to Western Australia last year and showed me photographs of the sea being filled with ships, all waiting for the tide to change so they could take that days output to China or India or wherever. Fortescue metals is clearly a company which takes advantage of the latest SAP innovations, and the CIO talked about making sure the IT department is not the “department of no”.

 

The next keynote was from the CIO of Fairfax Media, a company which is being forced to reinvent itself for the digital age, as traditional media sectors like printed newspapers go into terminal decline. He showed a chart of some recent research which suggested that just 4% of people looked at adverts in printed newspapers, and yet companies still spend 18% pf their advertising budget on such things. He is all too horribly aware that this is just because “we have always done it this way” and one day companies will wake up.

 

Afternoon Tea

 

The final meal of the day is Duck Consommé served with what they call corn silk, with chocolate, vanilla purée, rice and apple, and deep fried emu in a beer batter.

 

There were a large number of rock starts in attendance at this conference such as Jimmi Hendrix, Freddie Mercury, Michael Jackson, John Lennon and Buddy Holly. Afternoon tea is a good opportunity to swap business cards with them and talk about HANA and UI5.

 

SAP Mentor Tony de Thomasis talked about the various tools available to you when preparing for an SAP upgrade. He is not a big fan of “technical” upgrades, and subscribes to the view that you should take advantage of new features as soon as they become available, a message that was repeated by the various CIOs of forward looking companies who spoke at this conference.

This was a very hands on type of presentation, with live demonstrations as opposed to power point slides. I noticed when an error message popped up it referred to SAP GUI version 740, which I did not think was out yet, and he considered showing  us the version 5 of the NWBC but decided against it as it is still too flaky. As it turns out these will be released on 8th of October 2015.

 

The final talk of the day was from Katrin Pietsch from SAP talking about the “customer connection program”. SAP provide many free services to their customers, the general idea is that if there is a piece of functionality that is not present in standard SAP then if you band together in a group (like a user group) then chances are you can get SAP to add it to the standard product. As an example think of all the “repairs” you make to the standard system – if a large number of companies are making the exact same change then why not tell SAP. An example I can think of is the ERS transaction MRRL. The transaction date defaults to todays date, which is crazy, so I have seen a large number of companies  make a “repair” to the standard transaction so you can specify the transaction date. Instead of five hundred companies making the same modification and then having to go through the SPAU pain at upgrade time, why not tell SAP and see if they can’t add that field as standard?

 

To end the conference we had a foot long bratwurst infused with hundred-year-old Louis XIII cognac and topped with fresh lobster, picante sauce and Kobe beef seared in olive and truffle oil, washed down with the world's oldest cocktail, created with 1788 Clos de Griffier Vieux Cognac, 1770 Kummel Liqueur, 1860 Dubb Orange Curacao and early 20th century Angostura Bitters.

 

All in all a wonderful conference, packed with fascinating SAP demonstrations, good food, and excellent dustbins.

 

Cheersy Cheers

 

Paul

 

Viewing all 948 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>