Sharing session context between parent and external windows running on same host

    技术2022-05-11  56

    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.

     

     

        public   void  onActionCreateSupportRequest(com.sap.tc.webdynpro.progmodel.api.IWDCustomEvent wdEvent )   {    //@@begin onActionCreateSupportRequest(ServerEvent)        try {            ContextDTO contextDTO = new ContextDTO();            contextDTO.setBusinessParnterID("BUSINESS_PARTNER_ID");            contextDTO.setCustomerID("CUSTOMER_ID");            contextDTO.setWorkspaceID("WORKSPACE_ID");            String contextKey = ContextHelper.putContextDTO(contextDTO);            Map<String, String> urlParameters = new HashMap<String, String>();            urlParameters.put(ContextHelper.REQUEST_PARAM_NAME, contextKey);            String applicationUrl = WDURLGenerator.getApplicationURL(                    WDDeployableObject.getDeployableObjectPart(                            "demo.sap.com/callee""CalleeApp",                            WDDeployableObjectPartType.APPLICATION),                    urlParameters);            IWDWindow window = wdComponentAPI.getWindowManager()                    .createNonModalExternalWindow(applicationUrl,                            "Support Request");            window.show();        } catch (Exception exc) {            wdComponentAPI.getMessageManager().reportException(                    exc.getLocalizedMessage());        }    //@@end  }

     

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

     

     

       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.  Any comments or ideas for improvements are warmly welcomed and appreciated.

     

    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);            }        }    }}

     

     

    Regards,

    William Cui


    最新回复(0)