Additional Blogs by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
htammen
Active Contributor
0 Kudos

Enhance Web Dynpro Applications with Groovy Scripts

Scripting languages

Scripting languages give a lot of flexibility to the developers and the users of applications. The use of scripting languages could reduce development time and costs. Furthermore adoption to user demands and maintenance could be done in a more flexible way.
At the moment there are a lot discussions about scripting languages like Ruby, Perl, Jython, Python, Perl and Groovy.

Scripting languages are interpreted at runtime and the programs can therefore be changed and tested very easily without a compilation and deploy step. Just change your script and run it to see if your changes work.

Groovy is a scripting language that is based on Java. It is more flexible and natural than Java. Nearly all Java language features are also available with Groovy.
But thats not all. You can use Java statements in your Groovy scripts, call those Groovy scripts from your Java applications and exchange parameters between both. So Groovy scripts can enhance your Java applications significantly.

I don´t think that scripting languages can replace programming languages that are compiled to executables (like C++) or bytecode (like Java and C#) but they can make the life of programmers easier. If you use scripting languages to give enhancement ability to your applications you and your customers will be more flexible and therefore happier.
The SAP uses a similar approach in the ABAP world. It is called "Enhancement framework". Many of you may know parts of it as Badi, Customer exits or User exits. The aim of this framework is to give the user the possibility to enhance the applications written by the SAP in a flexible way. The same could be achieved by utilizing Groovy in Java applications.

A simple example

The following example shows how you can use Groovy in Web Dynpro applications. The purpose of the example is to calculate a gross price from a net price that is given by the user. The calculation of the gross price is done in a Groovy script that is called after the user pressed the "calculate gross price" button. 
The script in the example sets a tax rate and gives a discount of 5% if the net price is equal or higher than 200.00. At the end the tax and gross price are calculated.

// set the taxRate to xx percent
taxRate = 15.0
// if netPrice is higher than 200.00 give a 5 percent discount
discount = 0.0
if( netPrice >= 200.0) {
  discount = 0.05
}
netPrice = netPrice * (1 - discount)
// calculate the tax and gross price
tax = netPrice * taxRate / 100
return netPrice + tax
If you have several customers who calculate their gross price in different ways you only have to change the script which can be done without compiling and deploying.

The following screenshots show the program with two slightly changed scripts.

Application Architecture

The application is composed of a simple Web Dynpro for Java DC and an external Library DC. The external Library DC just contains the Groovy library that delivers the Groovy runtime.
The Web Dynpro DC uses the external Library DC and so deploys the Groovy jar file onto the server. 

If you want to use Groovy in more than just one application you should think about creating a J2EE Library DC and use this from all your applications. Then you don´t have to deploy the Groovy library several times

Downloading Groovy

Before you can develop your Web Dynpro application you have to download the Groovy library. This can be done here. You can also download a complete distribution of Groovy and extract the required library from this. Have a look at [1] for more details.

Creating the External Library DC

After you have downloaded the Groovy Library you have to create the Library DC that contains this library. You do this in the SAP Netweaver Developer Studio. See [3] for details on creating an External Library DC. Copy the Groovy Lib into the libraries folder of the DC, create two public parts (one for building and one for assembly) and build the DC. See the screenshot below for the folder structure of the Development Component Project.

Creating the Web Dynpro DC

The Web Dynpro DC is quite simple. It just contains one Web Dynpro component, one Web Dynpro application and one View. The view consists of one input field, one button, one textedit field and several textview fields for the output of  the calculation (see screenshots above).

To utilize Groovy in the view the first step is to create a GroovyShell instance. This is done in the wdDoInit-Method.

  //@@begin javadoc:wdDoInit()
  /** Hook method called to initialize controller. */
  //@@end
  public void wdDoInit()
  {
    //@@begin wdDoInit()
    Binding binding = new Binding();
    shell = new GroovyShell(binding);
   
    wdContext.currentContextElement().setDescription(
      "Within this script you can calculate the gross price of your product. You can do any calculation." +
      "The following input parameters are supplied: netPrice, taxRate and tax. \n" +
      "netPrice is set to the netPrice you entered in the corresponding input field.\n" +
      "taxRate is initialized to 18.00 % but you can override it in your script.\n" +
      "tax ist not initialized. You have to set it in your script.\n" +
      "The Web Dynpro application evaluates all these three parameters and outputs them as well as the " +
      "return value of your script which encloses the calculated gross price to the user."
    );
   
    // initialize the script
    StringBuffer script = new StringBuffer( "//  set the taxRate to xx percent\n" )
                                   .append( "taxRate = 18.0\n")
                                   .append( "//  if netPrice is higher than 200.00 give a 5 percent discount\n")
                                   .append( "discount = 0.0\n")
                                   .append( "if( netPrice >= 200.0) {\n")
                                   .append( "discount = 0.05\n")
                                   .append( "}\n")
                                   .append( "netPrice = netPrice * (1 - discount)\n")
                                   .append( "//  calculate the tax and gross price\n")
                                   .append( "tax = netPrice * taxRate / 100\n")
                                   .append( "return netPrice + tax\n" );
 
    wdContext.currentContextElement().setScript( script.toString() );
    //@@end
  }

The second line is the real interesting line. Here the GroovyShell that is responsible for the execution of the scripts is created. The binding object that is given to the constructor can be used to transmit parameters from your java application to the Groovy script. But this is done via the method GroovyShell.setVariable(..) in the next method.

The GroovyShell instance is defined between the @begin ... @others statements at the end of file. So it is a private instance variable of the class.

  //@@begin others
  private GroovyShell shell;
  //@@end

The next and last method to describe is the action handler of the button. In this method the script is evaluated and the calculated data is copied to the Web Dynpro View Context.

  public void onActioncalculateGrossPrice(com.sap.tc.webdynpro.progmodel.api.IWDCustomEvent wdEvent )
  {
    //@@begin onActioncalculateGrossPrice(ServerEvent)
    shell.setVariable( "netPrice", new Double( wdContext.currentContextElement().getOriginalNetPrice() ) );
    shell.setVariable("tax", new Double ( 0.0 ));
    shell.setVariable("taxRate", new Double ( 18.0 ) );
   
    Object value = shell.evaluate( wdContext.currentContextElement().getScript() );
   
    if( value instanceof java.lang.Number ) {
      wdContext.currentContextElement().setGrossPrice( ((java.lang.Number)value).doubleValue() );
    } else {
      String str = "Script does not return double value. The return type is " + value.getClass().getName();
      wdComponentAPI.getMessageManager().reportWarning( str );
    }

    Object netPrice = shell.getVariable( "netPrice" );
    if( netPrice != null && netPrice instanceof java.lang.Number ) {
      wdContext.currentContextElement().setNetPrice( ((java.lang.Number)netPrice).doubleValue() );
    } else {
      wdContext.currentContextElement().setNetPrice( 0.0 );
    }

    Object tax = shell.getVariable( "tax" );
    if( tax != null && tax instanceof java.lang.Number ) {
      wdContext.currentContextElement().setTax( ((java.lang.Number)tax).doubleValue() );
    } else {
      wdContext.currentContextElement().setTax( 0.0 );
    }

    Object taxRate = shell.getVariable( "taxRate" );
    if( taxRate != null && taxRate instanceof java.lang.Number ) {
      wdContext.currentContextElement().setTaxRate( ((java.lang.Number)taxRate).doubleValue() );
    } else {
      wdContext.currentContextElement().setTaxRate( 0.0 );
    }

    //@@end
  }

The first three lines initialize the variables netPrice, tax and taxRate that can be used inside the script. The netPrice is initialized with the value of the context attribute that is bound to die input field of the view.
The next line evaluates the script that is contained in the context attribute "script" and stores the return value in the local variable value. Then it is ensured that the return value is a java.lang.Number and if so it is assigned to the context attribute "grossPrice".
In the next three blocks the values of the script variables netPrice, tax and taxRate that eventually were changed in the script are read from the GroovyShell instance and assigned to appropriate context attributes.

To be complete the next screenshot displays the context of the view. The attributes grossPrice, netPrice, originalNetPrice, tax and taxRate are of type double. The other ones are string attributes.

Security

A big issue you should have in mind with scripting engines is security. When delivering the scripting engine to your customers in the way I described here your Web Application server is potentially vulnerable by hackers. Therefore you should ensure that the way the scripts get into your system is secure and only confidential people create scripts and/or you have to secure the evaluation of the Groovy scripts by use of a SecurityManager.
Because Groovy Scripts are compiled to Java classes behind the scenes it is well integrated with the Java security model. There are however some additional considerations you have to bear in mind when using Groovy. These are described in [4].

Conclusion

OK, thats all. You´ve seen that you don´t have to do much to use the Groovy Scripting engine from within your Web Dynpro applications. It´s up to you now to be creative in defining uses cases forthis appoach. Also have a look at the Groovy website [1]. There are much more possibilities than I could describe here.

I used scripting engines in the last twenty years of my business experience in several projects and languages. They always did a great job for me and I probably will also use them in the future.

Sources

[1] Groovy website
[2] Groovy download
[3] Creating an External Libary DC
[4] Groovy Security
4 Comments