Skip to Content

When creating an external window in Web Dynpro for Java, we normally use URL request parameters (i.e. HTTP GET) to transfer information from parent to external windows.  The usage of HTTP GET has advantages when the request is more like a simple query (i.e. it is a safe and repeatable operation such as a Google query, a generic lookup or help service).  Moving to the another side of HTTP GET, we could find the obvious disadvantages such as the parameter length limitation and the flattened key/value format making it difficult to transfer long and complex request objects.  Besides, the complete transparency of request parameters leads to the possibilities of malicious attacks.  More information could be found at http://www.w3.org/2001/tag/doc/whenToUseGet.html .

For the sake of security and abstraction, the programming model of Web Dynpro for Java has not explicitly exposed the HTTP POST and session attributes to developers.  Thanks to a new utility class WDScopeUtil available from NW04s and future releases, we could try to seek a tradeoff solution by making use of this helpful class.  Please notice that this solution only works when parent and external applications are running on same host.

Let’s first take a look at the API of this class, in which there are two main static methods:

static String get(WDScopeType scopeType, String key)

          Method get reads the value from the specified scope.

static void put(WDScopeType scopeType, String key, String value)

          Method put puts the value into the specified scope.

For detailed information please refer to corresponding Java doc on SAP help portal:

https://help.sap.com/javadocs/NW04S/current/wd/com/sap/tc/webdynpro/services/session/api/WDScopeUtil.html

As we may notice from the method signatures, String type is used to store specific value instead of generic Object  type.  I wrote a helper class called ContextHelper to wrap WDScopeUtil methods so that it would facilitate the process of putting/getting of complex session context objects based on JavaBeans XML format.

In this demo, the scenario consists of two local DCs – “demo.sap.com/caller” and “demo.sap.com/callee”.

There is a button labeled “CreateSupportRequest” in CallerApp that triggers an external  window of CalleeApp.

image

In CalleeApp, the context information received from CallerApp by a unique context key will be displayed in a form.

image


public void wdDoInit()
{
//@@begin wdDoInit()
IWDRequest request = WDProtocolAdapter.getProtocolAdapter()
.getRequestObject();
String contextKey = request
.getParameter(ContextHelper.REQUEST_PARAM_NAME);
if (contextKey != null) {
wdComponentAPI.getMessageManager().reportSuccess(
"contextKey: " + contextKey);
String contextXML = WDScopeUtil.get(
ContextHelper.REQUEST_SCOPE_TYPE, contextKey);
wdComponentAPI.getMessageManager().reportSuccess(
"contextXML: " + contextXML);
ContextDTO contextDTO = ContextHelper.getContextDTO(contextKey);
if (contextDTO != null) {
wdContext.currentContextElement().setBusinessPartnerID(
contextDTO.getBusinessParnterID());
wdContext.currentContextElement().setCustomerID(
contextDTO.getCustomerID());
wdContext.currentContextElement().setWorkspaceID(
contextDTO.getWorkspaceID());
} else {
wdComponentAPI.getMessageManager().reportException(
"Context DTO not found");
}
}
//@@end
}

In the end of this weblog, I would like to share with you of my ContextHelper as follows. Please feel free to use this helper and give me feedback if you like.


package com.sap.demo.callee.helper;

import java.beans.ExceptionListener;

import java.beans.XMLDecoder;

import java.beans.XMLEncoder;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.util.HashMap;

import java.util.Map;

import com.sap.demo.callee.dto.ContextDTO;

import com.sap.tc.webdynpro.services.sal.adapter.api.IWDRequest;

import com.sap.tc.webdynpro.services.session.api.WDScopeType;

import com.sap.tc.webdynpro.services.session.api.WDScopeUtil;

/**

  • A helper class for dealing with session context related operations

  • @author William Cui

*/

public class ContextHelper {

     public final static String REQUEST_PARAM_NAME = “contextKey”;

     public final static WDScopeType REQUEST_SCOPE_TYPE = WDScopeType.CLIENTSESSION_SCOPE;

     /**

     

  • Puts given context DTO into client session scope and returns a generated

     

  • context key

     

     

  • @param contextDTO

     

  •            given context DTO

     

  • @return a generated context key based on given context DTO

     

  • @throws IllegalArgumentException

     

  •             if given parameter is invalid

      */

     public final static String putContextDTO(ContextDTO contextDTO) {

          if (contextDTO == null)

               throw new IllegalArgumentException(“Invalid context DTO argument”);

          final String contextXML = getContextXML(contextDTO);

          final String contextKey = String.valueOf(contextXML.hashCode());

          WDScopeUtil.put(REQUEST_SCOPE_TYPE, contextKey, contextXML);

          return contextKey;

     }

     /**

     

  • Gets context DTO from client session scope with given context key

     

     

  • @param contextKey

     

  •            given context key

     

  • @return context DTO from client session scope with given context key

     

  • @throws IllegalArgumentException

     

  •             if given parameter is invalid

      */

     public final static ContextDTO getContextDTO(String contextKey) {

          if (contextKey == null)

               throw new IllegalArgumentException(“Invalid context key argument”);

          String contextXML = WDScopeUtil.get(REQUEST_SCOPE_TYPE, contextKey);

          ContextDTO contextDTO = parseContextDTO(contextXML);

          return contextDTO;

     }

     /**

     

  • Gets an XML representation of given context DTO

     

     

  • @param contextDTO

     

  •            given context DTO

     

  • @return an XML representation of given context DTO

     

  • @throws IllegalArgumentException

     

  •             if given parameter is invalid

      */

     public final static String getContextXML(ContextDTO contextDTO) {

          if (contextDTO == null)

               throw new IllegalArgumentException(“Invalid context DTO argument”);

          final ByteArrayOutputStream out = new ByteArrayOutputStream();

          final XMLEncoder xmlEncoder = new XMLEncoder(out);

          xmlEncoder.setExceptionListener(new ContextExceptionHandler());

          xmlEncoder.writeObject(contextDTO);

          xmlEncoder.flush();

          xmlEncoder.close();

          return new String(out.toString());

     }

     /**

     

  • Parses a context DTO from given context XML string

     

     

  • @param contextXML

     

  •            given context XML string

     

  • @return a context DTO from given context XML string

     

  • @throws IllegalArgumentException

     

  •             if given parameter is invalid

      */

     public final static ContextDTO parseContextDTO(String contextXML) {

          if (contextXML == null)

               throw new IllegalArgumentException(“Invalid context XML argument”);

          final ByteArrayInputStream in = new ByteArrayInputStream(contextXML

                    .getBytes());

          final XMLDecoder decoder = new XMLDecoder(in);

          decoder.setExceptionListener(new ContextExceptionHandler());

          final ContextDTO contextDTO = (ContextDTO) decoder.readObject();

          return contextDTO;

     }

     /**

     

  • An exception handling class for dealing with context transformation

     

  • exceptions

     

     

  • @author William Cui

      */

     private final static class ContextExceptionHandler implements

               ExceptionListener {

          public void exceptionThrown(Exception exc) {

               if (exc instanceof IOException) {

                    throw new RuntimeException(“Context transformation exception”,

                              exc);

               }

          }

     }

}

</pre>

Regards,

William Cui

To report this post you need to login first.

6 Comments

You must be Logged on to comment or reply to a post.

  1. Mauricio MiĆ£o
    Hi Willian,

    Thanks for this blog.
    I noticed in javadoc a strange statement:
    Class WDScopeUtil can be used to share data between applications… “Users must not rely on objects being available within the scope i.e. a get might fail even after a put with the same key has been done.”

    Have you ever faced a situation where the get failed?
    Do you know what SAP mean? If a get might fail there is a specific reason or situation?
    It concerns me as if a get might fail I can not rely on this solution for important information.

    Regards,
    Mauricio

    (0) 
    1. William Cui Post author
      Hi Mauricio,

      Sorry for late reply.

      Yes, I also noticed it. My guess is that client session cookies or something else may be unexpectedly cleared or modified so that a get might fail in this case. Usually we won’t meet this situation and could hardly prevent it, which is also the native vulnerability of web applications.

      What’s your idea?

      Regards,
      William

      (0) 
  2. Hello this great but whats about ContextDTO Class.
    You did mention it hardly. Please give me more
    information about this class.

    Reagards
    sas

    (0) 
  3. Prasanna Joshi
    Hi William,

    I read your Blog and I have a requirement where in I have a Hidden iView in Portal which sets an attribute in the Session. The same attribute is to be accessed into my Web Dynpro Application. Now I read few atricles and came across WDScopeUtil Class. I used the get() method of the WDScopeUtil class but I get a “null” value when I try to retrieve the Session attribute.

    Is it so that the attribute is getting lost or reset in the session?

    (0) 
  4. Andrea Mello
    Hi,
    I suppose that the contextDTO should be an IWDNode defined in the context view, is this true?

    In this case seems there is some problem converting the IWDNode to an XML string to store in the session.
    The method getContextXML() returns an empty xml.

    Where am I wrong?

    Thanks a lot,
    Andrea Mello
    andrea.mello@atosorigin.com

    (0) 
    1. William Cui Post author
      Hi Andrea,

      No, contextDTO is nothing but a plain Data Transfer Object (POJO, Java Bean) which contains the necessary information needed for transfer between.

      In case of the empty XML string from IWDNode object, it probably could be that there is no serializable attributes defined.

      Regards, William

      (0) 

Leave a Reply