Skip to Content

Introduction


Question about how to schedule tasks in SAP J2EE WAS is pretty popular on WAS, Java and Web Dynpro forums. For last couple of month I can count at lest 4 such questions:

In spite of such popularity corresponding functionality is not well described neither by help.sap.com nor by expert’s posts on SDN. On help.sap.com we can find some information and examples in section Developing Services -> SAP J2EE Engine Ready-to-Use Services. But development of WAS services is not a daily job of many developers, so it is hard to alight this section and moreover the information is pretty poor and tangled. In this blog I will try to make up lack of information about Timeout service and how you can use it. I will try to build a small background application which reads RSS feeds from SDN Web Dynpro forum every 5 minutes and stores it to the database.</p>


Timeout Service


To make task schedule possible we need to get reference to Timeout Service (interface com.sap.engine.services.timeout.TimeoutManager), implement timeout listener (interface com.sap.engine.services.timeout.TimeoutListener) and register timeout listener in Timeout service.

TimeoutManager interface contains following methods which can be interesting for us:


registerTimeoutListener
unregisterTimeoutListener
refreshTimeout
changeRepeatTime

registerSynchronousTimeoutListener
unregisterSynchronousTimeoutListener
refreshSynchronousTimeout
changeSynchronousRepeatTime

 

All of them taking instance of TimeoutListener interface as first parameter.
This interface having following structure:


public interface TimeoutListener
{
public abstract void timeout();
public abstract boolean check();
}

 

The TimeoutListener.timeout() method is called when timeout event raised.
The TimeoutListener.check() method returns true if the TimeoutListener.timeout() method has to be executed and false, if the code in the TimeoutListener.timeout() method is not needed.

We have 2 options for running our tasks (instance of TimeoutListener): synchronous and asynchronous. By synchronous mode instance of TimeoutListener registered on timeout manager is running only in one thread. By asynchronous mode instance of TimeoutListener can be shared among multiple threads. If we are using some critical resource like database connections we need to think about synchronization. We will see later how TimeoutListener.check() method can help us with this task.</p>


Web Component


As we are building pretty simple application, so I decided to use not WAS service as described on help.sap.com, but give a try to utilize Timeout service functionality in more trivial and well-known environment – Web Component, namely Servlet.

As you may know, servlets have a option to be launched for initialization by Web Container start using


public void init(ServletConfig cfg) throws ServletException

 

method from javax.servlet.Servlet interface.

Servlets should be marked properly in web.xml file using

<load-on-startup>tag.

For our example we will create Web Module DC


Web Module DC
 

and a generic servlet

!https://weblogs.sdn.sap.com/weblogs/images/37773/2_Servlet.PNG|height=348|alt=New generic servlet|width=349|src=https://weblogs.sdn.sap.com/weblogs/images/37773/2_Servlet.PNG|border=0!
 

Our servlet is not going to process any requests, so we can skip implementation of all do*() methods there. The only purpose of our servlet is to register new listener in Timeout Service by initialization and unregister by destroy of servlet.

To use TimeoutManager and TimeoutListener interfaces we need to add public part from appropriate DC. It is ”SAP-J2E”->”com.sap.engine.client.lib”Now we are ready with references setup and can come to listener implementation. As we said there are 2 methods in TimeoutListener interface that need to be implemented:


public class SDNRSSTimeoutListsner implements TimeoutListener {
private boolean inProcess;
private final String sdnRSSurl;
private SAXParser parser;

public SDNRSSTimeoutListsner(String _url) {
sdnRSSurl = _url;
SAXParserFactory factory = SAXParserFactory.newInstance();
parser = factory.newSAXParser();
}

public void timeout() {
inProcess = true;
try {
URL url = new URL(sdnRSSurl);
URLConnection urlConn = url.openConnection();

InputStream istream = urlConn.getInputStream();
InputSource is = new InputSource(istream);

parser.parse(is, rssDataHandler);
} catch (Exception e) {
e.printStackTrace();
} finally {
inProcess = false;
}
}

public boolean check() {
return !inProcess;
}
}

 

To implement synchronization for thread safety we use inProcess variable which is set to true when TimeoutListener.timeout() method starts and to false when it ends. We allow running our listener instance within thread only when it is not running by any other thread. Same effect we could achieve be using synchronous mode but I prefer asynchronous to show purpose of TimeoutListener.check() method.

Now we can register our TimeoutListener on Timeout Service manager. As we agreed all manipulation with timeout service we perform within lice cycle methods of generic servlet: init() and destroy(). We register our listener to be launched synchronously just after registration (0 seconds delay) and to be launched asynchronously every 300000 milliseconds (which is 5 minutes) afterwards. To be able to unregister our listener from timeout service we have to save reference in servlet`s class variables:


private TimeoutManager timeoutManager;
private TimeoutListener timeoutListener;
private RSSDataHandler rssDataHandler;

public void init(ServletConfig cfg) throws ServletException {
super.init(cfg);

try {
final Context context = new InitialContext();
timeoutManager = (TimeoutManager) context.lookup("timeout");
DataSource dataSource = (DataSource)context.lookup(
"java:comp/env/jdbc/TIMEOUT");

rssDataHandler = new RSSDataHandler( dataSource.getConnection() );

timeoutListener = new SDNRSSTimeoutListsner(
"http://forums.sdn.sap.com/rss/rssmessages.jsp?forumID=52" );

timeoutManager.registerTimeoutListener( timeoutListener, 0, 300000);
} catch (Exception e) {
e.printStackTrace();
}
}

public void destroy() {
super.destroy();

timeoutManager.unregisterTimeoutListener(timeoutListener);
}

 


RSS SAX Handler


To parse data coming from RSS channel and to store parsed data to DB we implement SAX handler (I won`t describe it too detailed because it is out of scope of this blog)


EAR component


To package and deploy our Web Module DC we will create EAR DC


EAR DC
“New->META-INF/data-source-aliases.xml”.

!https://weblogs.sdn.sap.com/weblogs/images/37773/8_addDatasourceAlias.PNG|height=164|alt=Add DataSoutce Alias|width=585|src=https://weblogs.sdn.sap.com/weblogs/images/37773/8_addDatasourceAlias.PNG|border=0!
 

In dialog popup specify name of alias (TIMEOUT)

!https://weblogs.sdn.sap.com/weblogs/images/37773/90_setAliasName.PNG|height=314|alt=DataSource Alias Name|width=441|src=https://weblogs.sdn.sap.com/weblogs/images/37773/90_setAliasName.PNG|border=0!
 


Dictionary component


And the last step is to define database table which will contain downloaded and parsed data.

We create dictionary DC


Dictipnary DC
 

And define table structure


image

 

In next blog I will try do develop real WAS service which will utilize Timeout service and will solve another popular issue – how to pass structured objects between components within SAP J2EE WAS.

To report this post you need to login first.

4 Comments

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

  1. Valery Silaev
    Maksim,

    At last you start blogging on SDN 😉
    My congratulations with your first post.

    Guess editors will choose it as “Editor Pick” while topic is very popular.

    However, I can suggest better way to register/unregister Scheduler service listener:

    instead of “load-on-startup” servlet it is better to use javax.Servlet.ServletContextListener, wich provides hooks to complete Web application startup/shutdown events.

    Thoughts?

    Valery

    (0) 
    1. Maksim Rashchynski Post author
      Hi Valery,

      Well, actually idea was not to build spider but show how to use Timeout service, because I`m going to show in next blog how it can be used for building WAS service which will implement kind of global storage of objects: we will register object on it, service will generate global key and return back. Afterwards another component can get the object by global key. And the Timeout listener will remove expired objects. The implementation is done and running on my local laptop but I need to document it and make screen shoots for blog. BTW, any doubts about such approach (with global storage of structured objects)?

      Best regards, Maksim Rashchynski.

      (0) 

Leave a Reply