cancel
Showing results for 
Search instead for 
Did you mean: 

How to suspend thread of iView?

Former Member
0 Kudos

Hello,

Does somebody know how to suspend thread of iView? I'd like to synchronize two iViews.

Best Regards,

Josef Motl

Accepted Solutions (1)

Accepted Solutions (1)

detlev_beutner
Active Contributor
0 Kudos

Hi Josef,

I once had a similar request but didn't resolve it the "clean" way. But it's a very interesting thing in general and so I would like to give a very general solution (working on, expect it within the next hours).

Just one question to clarify, for me not running in the wrong direction:

You have one page with two (in general: two or more) iViews, and you want these to syncronize in the sense that you define some sync point within each iView where you want to be sure for each iView IV(n) that all of the other iViews have reached their sync point before IV(n) is going on, right?

(And just for my interest: You want some iView to put some value into the session for example and some other to consume this value, right?)

Best regards

Detlev

Former Member
0 Kudos

Hi Detlev,

Thank you for your favour. Yes, I meant synchronizing in sense of sync point you described.

Other communication is not necessary. But I'm interested in. I can put value to session and consume by other iView? How can I do that? I think this code..

IPortalComponentRequest aRequest = (IPortalComponentRequest)getRequest();

IPortalComponentSession componentSession = aRequest.getComponentSession();

.. get componentSession, which cannot be used for value-sharing of iViews.

Best Regards,

Josef

detlev_beutner
Active Contributor
0 Kudos

Hi Josef,

OK, here it comes

First, to warm up, about your question concerning value sharing across components. For sure, as you have written, the IPortalComponentSession is only accessible within the same component. That's why it has it's name Anyhow, from IPortalComponentSession you are able to access the (common) HttpSession. This you can use to share data within one HttpSession but between different components. Just be careful using names... (at least use namesspaces).

So, this we also need in here. Not really to share "data", but to share the locker object.

My implementation example is straight forward. I have implemented an example class, it's just this:


package com.btexx;

import javax.servlet.http.HttpSession;

import com.sapportals.portal.prt.component.AbstractPortalComponent;
import com.sapportals.portal.prt.component.IPortalComponentRequest;
import com.sapportals.portal.prt.component.IPortalComponentResponse;
import com.sapportals.portal.prt.component.IPortalComponentSession;

public class TestComponent extends AbstractPortalComponent {
  public void doContent(IPortalComponentRequest request, IPortalComponentResponse response) {
    String compName = request.getComponentContext().getComponentName();
    IPortalComponentSession pcSession = request.getComponentSession();
    System.out.println(compName + " has reached it's synch point.");
    LockerObject.waitForFriends(pcSession, 2);
    System.out.println(compName + " has determined that all friends also have reached their synch point.");
  }
}

The line


LockerObject.waitForFriends(pcSession, 2);

defines the sync point. Imagine two different iViews, also defined by two different classes, doing some stuff, and somewhere defining this sync point. It doesn't matter where, you must only be sure that the "friend" we are waiting for in fact will appear (in words of portal environment: That the second iView will be called; you can never place such a component alone on a page without waiting to death...).

Now to the locker class:


package com.btexx;

import javax.servlet.http.HttpSession;
import com.sapportals.portal.prt.component.IPortalComponentSession;

public class LockerObject {
    
  private final static String LOCKER_ATTRIBUTE = "com.btexx.LockerObject";
    
  private int friends = 0;
  private int visited = 0;
    
  public LockerObject(int i) {
    friends = i;
  }
    
  synchronized public void waitForFriends() {
    visited++;
    if (friends == visited) {
      notifyAll();
    } else {
      try {
        wait();                
      } catch (InterruptedException ie) {
      }
    }
  }
    
  public static void waitForFriends(IPortalComponentSession pcSession, int i){
    HttpSession session = pcSession.getHttpSession();
    LockerObject lo;
    synchronized (session) {
      lo = (LockerObject) session.getAttribute(LOCKER_ATTRIBUTE);
      if (lo == null) {
        lo = new LockerObject(i);
        session.setAttribute(LOCKER_ATTRIBUTE, lo);
      }
    }
    lo.waitForFriends();
    session.removeAttribute(LOCKER_ATTRIBUTE);
  }
}

Also not that much stuff. The static helper method just extracts the HttpSession and looks inside, if there is already a locker object inside. Must be synchronized, because we have to work on the same locker object...

Now, we are sure that there is a locker object within the shared HttpSession, we call waitForFriends(). The locker object counts the additional friend who has visited the locker object and checks if all needed friends have been there. If not, it calls wait() to lay this thread to sleep. If yes, the method runs without stopping and notifies all sleeping threads that the battle for the LockerObject's lock can start again.

Create a PAR file out of this with portalapp.xml as follows:


<?xml version="1.0" encoding="utf-8"?>
<application>
  <application-config/>
  <components>
    <component name="TestComponentA">
      <component-config>
        <property name="ClassName" value="com.btexx.TestComponent"/>
        <property name="SecurityZone" value="com.btexx/high_safety"/>
      </component-config>
      <component-profile/>
    </component>
    <component name="TestComponentB">
      <component-config>
        <property name="ClassName" value="com.btexx.TestComponent"/>
        <property name="SecurityZone" value="com.btexx/high_safety"/>
      </component-config>
      <component-profile/>
    </component>
  </components>
  <services/>
</application>

Then create two iViews, one out of TestComponentA and one out of TestComponentB. Create a page, put both iViews on it, put the page to a test role, define this as entry point, assign the role to your user and click on it.

A typical output will be

SynchronizationExample.TestComponentA has reached it's synch point.

SynchronizationExample.TestComponentB has reached it's synch point.

SynchronizationExample.TestComponentB has determined that all friends also have reached their synch point.

SynchronizationExample.TestComponentA has determined that all friends also have reached their synch point.

So, typically: ABBA or BAAB; typically, but not necessarily, because we didn't synchronize the output, so in theory you could also get

SynchronizationExample.TestComponentA has reached it's synch point.

SynchronizationExample.TestComponentB has reached it's synch point.

SynchronizationExample.TestComponentA has determined that all friends also have reached their synch point.

SynchronizationExample.TestComponentB has determined that all friends also have reached their synch point.

Anyhow, first each component will reach it's sync point before going on. That's what we wanted.

All this was inspired by http://java.sun.com/docs/books/tutorial/essential/threads/waitAndNotify.html (look there for technical questions concerning threads, concurrency, locking, wait etc)

Just one more remark: <i>If</i> you have two components where C1 just waits for C2 (always in this order) to be "ready", you can do this far more easy (but less elegant) by:

C1:


boolean c2ready = false;
do {
  c2ready = "ready".equals(httpSession.getAttribute("com.btexx.c2");
} while (!c2ready);
httpSession.removeAttribute("com.btexx.c2")

C2:


httpSession.setAttribute("com.btexx.c2", "ready");

Hope this was a ten-pointer in your eyes

best regards & have a nice weekend

Detlev

Former Member
0 Kudos

Hi Detlev,

thank you for your comprehensive answer. Now, I have another (more urgent) request, so I will come back to this issue later. Thank you again, I'll surely use result of your work.

Best Regards,

Josef

Answers (0)