Additional Blogs by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member
0 Kudos

Working in a very large project with an impressive amount of WD components I need a way to share some data between all of them. Such technique like external context mapping were not desired for me, because it would increase the amount of dependencies between components and would add lots of effort in mapping the context. That would also reduce the maintainability, because  every change on the shared component would lead to adaption of the context of externally mapped components. So I started to search for another way to implement such a "cross cutting" functionality without doing changes on every component using it. The requirements for that could be summarized as follows:

  • Introduce a method which can be easily accessed from everywhere  by means of Java (e.g. a static method) and store an object sharing it among different wd components in the context of the user session.
  • Let Web Dynpro control the lifecycle of this object
  • If the WD application is disposed, the object should do the same
  • Every WD component should be able to access the same instance of the object in the user session once created and modify it.

As you can see here, it is a typical functionality of the session context in e.g.  a servlet. However WD introduces much higher layer of UI abstraction, so going back to the roots using such things like WDProtocolAdapter would not be a good option. So going through Java Doc I've found a solution which is based on the IWDModel. Let me introduce an example to explain how it works.

First of all you have to implement the IWDModel interface. I implemented it only partly providing the values for two methods. All others still return null. Our implementation will also hold an object which is shared in the context of the application. That is assured by the scope type we return in the getModelScopeType method - WDModelScopeType.APPLICATION_SCOPE and in the way how we will register it by WD later on.

/**
* The object holder shared in the context of the application.
*
* @author Dimitri Lubenski
*/
public class SharedObjectHolder implements IWDModel {

     private Object sharedObject;
     
     public String getModelInstanceId() {
          return String.valueOf(this.hashCode());
     }

     public WDModelScopeType getModelScope() {
          return WDModelScopeType.APPLICATION_SCOPE;
     }

     public Object getSharedObject() {
          return sharedObject;
     }

     public void setSharedObject(Object sharedObject) {
          this.sharedObject = sharedObject;
     }

...     

The instantiation of our SahredObjectHolder model is done by the WDModelFactory which will manage the lifecycle of the model for us. Let us create a static method in another class for that. We will also use generics to avoid casts in the code using our method.

/**
* Manages the IWDModel instances.

* @author Dimitri Lubenski
*/
public class SharedObjectManager {

     @SuppressWarnings("unchecked")
     public static  T getSharedObject(Class modelClazz)
     {
          return (T)WDModelFactory.getModelInstance(modelClazz, WDModelScopeType.APPLICATION_SCOPE);
     }
}

Called first, the WDModelFactory will instantiate our object and manage it, till the application is disposed. Hence calling the same method again will return the same object instance which was created during the first invocation. Let us check that with this code added to a WD button action handler:

  public void onActionGetId(com.sap.tc.webdynpro.progmodel.api.IWDCustomEvent wdEvent )
  {
    //@@begin onActionGetId(ServerEvent)
      SharedObjectHolder sharedObjectHolder = SharedObjectManager.getSharedObject(SharedObjectHolder.class);
     
      Object sharedObject = sharedObjectHolder.getSharedObject();
     
      IWDMessageManager mm = wdComponentAPI.getMessageManager();
     
      if (sharedObject==null) {
           sharedObjectHolder.setSharedObject("Hello World");
           mm.reportSuccess("Object created first with the ID =" + sharedObjectHolder.getModelInstanceId());
      }
      else {
           mm.reportSuccess("Object is alredy created. Value is " + (String)sharedObject);
      }
     
    //@@end
  }

In the screens below you can see the results of clicking the button first time and the second time.

Please keep in mind, the provided code has been tested on the CE 7.1 EhP1. Looking shortly into Java Doc of NW 04s I've found the same interfaces, so I suppose it to work there also.

What next?

The code displayed above is pretty well for my project because I need to share only one object. If I would need to share two I would have following options:

  • Create a new instance variable in the SharedObjectHolder
  • Derive a new class from the IWDModel and register it.

Both of them may be suboptimal depending on your project and need additional code changes. So it might be better to use java 5 generics with the same implementation of the SharedObjectHolder. To assure uniqueness of shared object instances with different class types an additional id can be passed to the WDModelFacrtory(see overloaded methods of getModelInstance)

6 Comments