Skip to Content

Table of Contents

Summary

Scope of this article

In this article, we provide a step-by-step tutorial how to develop Web Dynpro Java components that can be extended by customers without modification. We show how to develop and deploy a sample component that provides a view container for customer extensions, transform this view container into an extension point and provide a default implementation.

We also present the customer’s perspective, showing how to use this extension point to hook one’s own implementation into the extension point’s container. We conclude our tutorial with an explanation of how to switch between different deployed variants of a customer’s extension. All customer activities can be performed without modifying the originally delivered and deployed vendor application.

Applies to

Our tutorial refers to SAP Netweaver AS Java 7.31, using Netweaver Developer Studio 7.31 SP08.

Target audience

Architects, Developers, Product Management

Sample UseCase

For the purpose of this tutorial, we introduce a minimal sample UseCase. We want to develop a dialogue, containing a panel that allows the user to enter one single string value. After clicking the button, this value shall be stored in the application’s context and the same dialogue shall be shown again. Furthermore, the UI has to contain a second panel which shall be a placeholder for customers who can integrate their own visual representation of the main application’s context value. Customers shall be able to develop and deploy their individual UI showing the main application’s context value without modifying the vendor product.

The following image shows a mock-up of the applications UI.

SCN WD4J Extensibility MockUp.jpg

By default, the lower panel shall simply display the value that has been entered above.

Architecture Overview

In order to realize this UseCase, we will use the standard SAP extensibility capabilities. We therefore will define a standard Web Dynpro Java Window with one default View, realizing the standard dialogue. Within this dialogue, a generic UI container will be placed. The definition of the actual view within this container will be delegated to a self-defined Component Interface, which can then be implemented by the customer according to his needs. In order to give customers the possibility to easily inject their implementation of the interface into the vendor’s application, this interface will also be declared as an ExtensionPoint.

The following UML diagram shows this design formally:

SCN WD4J Extensibility UML.jpg

As we can see, the MainApplication software component uses the interface ICompInt with its contained InterfaceView ICompIntIV and its context attribute. Furthermore, a default implementation of this interface is provided in the software component Default Implementation.

In the following, we will present a step-by-step guide how to implement this architecture.

Development of the Vendor Product

Definition of the Software Component for the Standard UI

We start by creating a new Software Component (SC). We call it THE_PRODUCT, developed by vendor vendor.example.org. In the following steps, we declare dependencies from this component to all possible standard components.

/wp-content/uploads/2013/08/001_266860.png

With this new SC, we now create the standard product UI. We therefore switch to the Composite Designer perspective and create a new development component of type Web Dynpro, naming it prod_ui.

/wp-content/uploads/2013/08/003_268085.png/wp-content/uploads/2013/08/004_268086.png

Definition of the Component Interface for Customer Extensions

In order to specifiy the interface view a customer implementation has to provide, we now define the component interface for the potential customer extensions. This interface will also become the extension point later in the development process.

We begin by creating  a new component interface within the development component, naming it ICompInt.

/wp-content/uploads/2013/08/005_268089.png/wp-content/uploads/2013/08/006_268090.png

Within this component interface, an interface view named ICompIntIV is added.

/wp-content/uploads/2013/08/007_268097.png/wp-content/uploads/2013/08/008_268098.png

Next, we add the context attribute that will be available to all implementors of our component interface. For our simple example, the attribute will be a simple string value. The attribute is added to the interface controller of the interface component (double click on the controller and chose the Context tab in the properties view).

/wp-content/uploads/2013/08/009_268110.png/wp-content/uploads/2013/08/010_268111.png

Building the Main Application Component

Now, we can design the main dialogue, i.e. the application that will use the recently created interface in order to include the customer specific enhancement. Therefore, we use the wizard to create a new component with a default window and a default view.

/wp-content/uploads/2013/08/011_268116.png/wp-content/uploads/2013/08/012_268117.png/wp-content/uploads/2013/08/013_268139.png

Next, we design the main dialogue. The important aspect is the inclusion of a generic ViewContainerUIElement, which can later be filled by the customer implementation.

/wp-content/uploads/2013/08/014_268140.png

In order to be able to use the previously designed interface, we have to add a component usage of the interface to our main dialogue component.

/wp-content/uploads/2013/08/015_268142.png/wp-content/uploads/2013/08/016_268143.png

Now, that we have defined the usage of the interface, we can embed the interface view (which is, as you might remember, part of the component interface) into our main application’s window. To be precise, the interface view is embedded within the view of the generic ViewContainerUIElement which is part of our main dialogue.

/wp-content/uploads/2013/08/017_268144.png/wp-content/uploads/2013/08/018_268148.png/wp-content/uploads/2013/08/019_268149.png

In order to show that the data transport from the main application to the customer extension works, we add a context attribute to the main application, which is bound to the input field, so that the user can enter data here. This data will then be transfered to the interface’s context attribute and can be displayed by any customer implementation. Therefore, we simply add a context attribute to the main application’s component controller and map this attribute to the component interface’s attribute.

/wp-content/uploads/2013/08/020_268169.png/wp-content/uploads/2013/08/021_268170.png/wp-content/uploads/2013/08/022_268171.png/wp-content/uploads/2013/08/023_268175.png/wp-content/uploads/2013/08/024_268176.png

Since we want to input data to this context attribute from the main dialogue, we have to create a mapping from the view’s context to the component controller’s context, thus getting access to the main components context attribute. This attribute is the bound to our input field.

/wp-content/uploads/2013/08/025_268177.png/wp-content/uploads/2013/08/026_268181.png/wp-content/uploads/2013/08/027_268182.png/wp-content/uploads/2013/08/028_268183.png/wp-content/uploads/2013/08/029_268184.png

Finally, we add a button. This button has the sole purpose to trigger a roundtrip to the server, thus updating the Web Dynpro‘s context.

/wp-content/uploads/2013/08/030_268190.png/wp-content/uploads/2013/08/031_268191.png

By creating an application that starts our main dialogue via it’s default plug, we finish the creation of the main component.

/wp-content/uploads/2013/08/032_268193.png/wp-content/uploads/2013/08/033_268194.png/wp-content/uploads/2013/08/034_268195.png/wp-content/uploads/2013/08/035_268196.png

Creating a Default Implementation of the Component Interface

Since our application shall be designed to also work without any active customer implementation, we have to provide a default implementation of the component interface. Therefore, we again use the component creation wizard. We also already specify that we want to implement the previously created component interface.

/wp-content/uploads/2013/08/036_268197.png/wp-content/uploads/2013/08/037_268198.png/wp-content/uploads/2013/08/038_268211.png

In the component’s view, which, as an example, will be designed containing a Label and a disabled InputField, we need access to the context attribute we implement from the component interface. This can be achieved with a mapping to the interface component usage. This mapped attribute is then used as a binding for our InputField.

/wp-content/uploads/2013/08/039_268284.png/wp-content/uploads/2013/08/040_268285.png

Using the Interface Implementation as a Default Implementation

As you might have noticed, we did not yet tell the main component that our recently created implementation of the component interface has to be used as a default implementation. This has to be done programmatically, i.e. we have to open the Java editor for our main component’s controller and modify the wdDoInit() method, so that it looks as follows:

  //@@begin javadoc:wdDoInit()
  /** Hook method called to initialize controller. */
  //@@end
  public void wdDoInit()
  {
    //@@begin wdDoInit()
            // create an instance of the component for the interface usage
            wdThis.wdGetICompIntComponentUsage().
               createCoponent("org.example.vendor.prod_ui.wd.comp.defextimplcomp.DefExtImplComp");
    //@@end
  }

Creating the Extension Point

If we want to make it possible to exchange the implementation of the component interface without modifications, we also have to create a relationship between the main component and it’s potential interface implementation. In lack of a customer extension, we therefore define a usage relationship between the main component and our default implementation.

/wp-content/uploads/2013/08/041_268313.png/wp-content/uploads/2013/08/042_268314.png/wp-content/uploads/2013/08/043_268315.png

To turn this usage into an extension point, we have to switch to the Composite Designer perspective. In this perspective, we right-click on the main component and choose Relations from the context menu. In the resulting view, we select the relationship from the main component to the default implementation, right-click again and select Create Extension Point. By confirming the default proposals in the following steps of the wizard, we add the newly created extension point to the public part ec of the main component, making it visible to any other software component.

/wp-content/uploads/2013/08/044_268316.png/wp-content/uploads/2013/08/045_268317.png/wp-content/uploads/2013/08/046_268318.png/wp-content/uploads/2013/08/047_268319.png

Since this public part shall be usable by any arbitrary component, we finally have to set the permissions accordingly. So we switch perspectives again and head over to the Development Infrastructure perspective. There, we open the Component Properties of our component prod_ui. On the permissions tab, we click on Unrestrict Access and confirm the following pop-up. As a last step, we unrestrict access for the public part ec of the main component, too.

With all these steps, we have created an application, containing a simple Web Dynpro Java component with a component interface and a simple default implementation. We can check out this version, as it would be delivered by the software vendor, by running the application. This is what we get as a result.

DefaultScreenshot.png

Now that we have presented the vendor side, i.e. how to create an extensible Web Dynpro Java application, we will switch sides and explain how customers can develop and deploy their own implementation.

Development of the Customer Extension(s)

As a customer, we first have to define our own product which will be the “container” for our extensions. We call it THE_EXTENSION in namespace customer.org. When defining the product, it is import to add a reference to the vendor product THE_PRODUCT as a dependency, in addition to all SAP standard components.

/wp-content/uploads/2013/08/051_268493.png/wp-content/uploads/2013/08/054_268494.png

Developing and Deploying a First Extension

Within this product, we then create an extension. Therefore, we right-click on THE_EXTENSION and select Create Extension. Since we have access to the sources of the vendor product, we select the option Product with Sources and select the referenced product THE_PRODUCT. An extension for (the only available) extension point ICompInt shall be developed, so we select this one.

/wp-content/uploads/2013/08/056_268495.png/wp-content/uploads/2013/08/057_268496.png/wp-content/uploads/2013/08/058_268497.png/wp-content/uploads/2013/08/059_268498.png

Since there is no development component within this product yet, we add a new DC of type Web Dynpro and name it ext1.

/wp-content/uploads/2013/08/060_268506.png/wp-content/uploads/2013/08/061_268503.png/wp-content/uploads/2013/08/062_268504.png/wp-content/uploads/2013/08/063_268505.png

To finish the creation of the extension, we select the newly created DC and give the new extension the name Ext1.

/wp-content/uploads/2013/08/064_268507.png/wp-content/uploads/2013/08/065_268508.png

Please note that the automatically created window within Ext1 already implements the interface view CompIntIV, which is the interface view we defined in our component interface. To complete this window, we next create the view that will later be displayed within the main dialogue. We name it ExtView1.

/wp-content/uploads/2013/08/066_268509.png/wp-content/uploads/2013/08/067_268510.png

As this view shall display the context attribute we received from the main component, we have to add a mapping from the view’s context to the component controller’s context. As you will see when selecting the component controller of Ext1 in the mapping wizard, the attribute extensionAttribute is already there, since our component is an implementation of the component Interface which has been provided by the vendor.

/wp-content/uploads/2013/08/070_268514.png

We finish the design of the view, adding for instance a Label and a disabled TextInput field and bind the TextInput field to the mapped context attribute. Now that the extension has been developed, we can simply deploy it to the application server. If we now run the main application again (please note that we did NOT do any modifications to the main application, nor did we have to change any kind of configuration of the main application), you will note that instead of the default implementation, the application now shows our extension view in the respective panel.

Extension1ScreenShot.png

Developing and Deploying a Second Extension

To demonstrate the possibility to alternatively deploy an other extension, we develop a second extension according to the previous one, but with a different design of the view. After building and deploying this second extension, you will see that the newly deployed extension is automatically used when running the main application again.

Extension2ScreenShot.png

Reverting to the First Extension

But what if we want to switch between the two extensions? If we switch back to the Composite Designer perspective, we will see that both extensions are shown as development components, with the icons signalling either the state inactive or active . After right-clicking on the one we want to activate (Ext1), we can chose Activate Extension from the context menu. After re-deploying the extension product, the main application then uses extension one again.

Reverting to the Original State

Finally, by deactivating all extensions and re-deploying the extension product, the original default implementation is used again, and the application works as it was delivered by the original vendor.

About the Author

Michael Guppenberger is a Lead Software Consultant at msg systems ag. He mainly focuses on the software architecture of standard products for various SAP platforms.

To report this post you need to login first.