UI Integration between Siebel and Legacy

Hi, folks!

I can’t tell you that I think based on the market defaults, and based on best practices. So… even if this is not the best way (or the right way) to implement this kind of thing, I’ll not go on this issue. :)

Scenario

One of our customers has two types of UI integrations between Siebel and Legacy web applications.

In one of then, when user clicks on a specific button, Siebel should open a Legacy web application on a Modal Popup (that prevents user from interacting with Siebel while in the popup). User interacts with it (doesn’t matter how), and at some point, Legacy should interact with Siebel.

Siebel_HI_Popup_Scenario

In the another one (actually, it was our first alternative to make it work better in Open UI, maintaining High Interactivity as-is), when user clicks on a specific button, Siebel should go to another view, that opens a Legacy web application within (using Symbolic URL). User interacts with it (doesn’t matter how), and at some point, Legacy should interact with Siebel.

Siebel_SymbolicURL_Scenario

 

In both cases, they implemented their solution using ActiveX, with something like this:

var siebelApp = new ActiveXObject("Siebel.Desktop_Integration_Application.1");
var bs = siebelApp.GetService("SomeBusinessService");
var psIN = siebelApp.NewPropertySet();
var psOUT = siebelApp.NewPropertySet();
bs.InvokeMethod("SomeMethod", psIN, psOUT);

Our job on this customer was to turn on Open UI, and keep Siebel up-to-date. It means that we should install Siebel updates, quick fixes, patch sets, and so on, and keep everything working after that.

Problem

The biggest problem on this approach, is that ActiveX is not present on the other browsers than Internet Explorer. So… no problem, right? Wrong! For two reasons:

Solution (Oracle’s solution)

Oracle suggested that we could implement some kind of java applet (like the old CTI Toolbar) to communicate with the Legacy web application and with Siebel. I don’t even know how to do this… Furthermore, they told us that this approach will stop to work very soon (late 2015, when Google Chrome plans to stop supporting NPAPI architecture).

Solutions (my solutions for this project)

  • Siebel Java Data Bean: This approach can be used on any Java Web Application to interact with Siebel. Thus, it implies on creating a new session for these interactions. So… no UI interactions. In this case, we cannot use it because our interactions need to occur on the same user session. Further, the Legacy web application was a black box for us. We’re able to change some html and javascript files only.
  • Passing theApplication() as parameter: When working with Browser Scripts, we are working with Javascript. It means that Siebel Web Client, even on High Interactivity, have a “hidden” API to interact with (like Open UI). So… we’re able to pass theApplication() context as parameter to the child windows/popups with:
    • window.opener, to get the parent window context, when trying to communicate between a child window (opened with window.open) and parent window;
    • window.dialogArguments, to get the second parameter passed on window.showModalDialog, when trying do communicate between a child popup and the window that calls it;

    The main problem is that these approaches considers that all windows and popups came from the same domain, port and protocol, and it’s not always true, when integrating two different systems. There are some workarounds that I’ll describe later on this post.

  • Javascript postMessage: If there is a way to include javascript code on both sides (Siebel and Legacy), you can use postMessage to do the job, without dealing with CORS. The main idea here, is to create a “consumer” on Siebel side, and a “producer” on the Legacy side, and using the Browser context to act as a “messenger” (that receives messages, and takes it to who is listening to it).
    • Siebel-side example:
      // Create IE + others compatible event handler
      var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
      var eventer = window[eventMethod];
      var messageEvent = (eventMethod == "attachEvent") ? "onmessage" : "message";
      
      // Listen to message from child window
      eventer(messageEvent, function (event) {
       if (event && event.data && event.data.method) {
       switch (event.data.method) {
       case "invokeBS":
       if (event.data.serviceName && event.data.serviceMethod) {
       var bs = SiebelApp.S_App.GetService(event.data.serviceName);
       var inPS = SiebelApp.S_App.NewPropertySet();
       var outPS = SiebelApp.S_App.NewPropertySet();
      
       outPS = bs.InvokeMethod(event.data.serviceMethod, inPS);
       // ...
       }
       break;
      
       // ...
       }
       }
      }, false);
    • Legacy-side example:
      var siebelMessage = {
       method: "invokeBS",
       serviceName: "SomeBusinessService",
       serviceMethod: "SomeMethod",
       serviceInput: inPS
      };
      
      var siebelWindow;
      for (siebelWindow = window.parent; siebelWindow != siebelWindow.parent; siebelWindow = siebelWindow.parent);
      siebelWindow.postMessage(siebelMessage, "*");

    The main problem is that there is no easy way to turn this communication bi-directional. It’s only a producer-consumer solution, so… you can invoke anything from Legacy to Siebel, but you can’t take the results (return) back easily. And by the way… you cannot have any aditional static custom Javascript code on Siebel High Interactivity easily (without inserting it on a vanilla javascript file). So, it’s only good for simple interactions, and for Open UI.

At the end, I wrote a little (and not definitive/final) javascript library to be used in this project. It deals with these client-side interactions (ActiveX, postMessage and Context as parameter) automagically. It’s very simple, and is temporarily available here.

CORS (Cross-Origin Resource Sharing)

I’ll not describe it in details. If you want to know more about it, consider reading this.

Dealing with CORS

The default way to deal with CORS is including the allow rules on the response header of the resource origin. To do this, you can include something like this (below) in your apache-based web server’s configuration file (httpd.conf):

...
LoadModule headers_module modules/mod_headers.so
...
# Allow "legacydomain" domain to access my own domain resources
<Directory />
 Header set Access-Control-Allow-Origin "legacydomain"
 Header set Access-Control-Allow-Headers "Origin,X-Requested-With,Content-Type,Accept"
 Header set Access-Control-Allow-Methods "GET,PUT,POST,OPTIONS,DELETE,HEAD,COPY"
 Header set Access-Control-Max-Age 3600
</Directory>
...

More details here.

But, as I told before, I won’t go always by the default path… So, in my mind, i think that “Simplest is always Better”. Going in this way, I found a way to make client’s browser to believe that two (or more) different web applications are “the same”, so… no CORS, as they’re all on the same domain, port and protocol.

To do so, I’d created in our Siebel web server (Apache-based web server) some kind of proxy to the Legacy web application, as follows:

...
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
...
<IfModule proxy_module>
 ProxyRequests Off
 <Proxy>
 Order deny,allow
 Allow from all
 </Proxy>

 ProxyPass /legacy/ http://legacydomain:8080/appName/
 ProxyPassReverse /legacy/ http://legacydomain:8080/appName/
 ProxyPassReverseCookieDomain siebeldomain legacydomain
 ProxyPassReverseCookiePath /appName/ /legacy/
</IfModule>
...

It means that, following this example…

http://legacydomain:8080/appName/*

… will be accessible as…

http://siebeldomain/legacy/*

Everything worked like a charm, because our client’s browsers believes that they’re all under the same domain, port and protocol. When sending requests to Legacy thru Siebel domain, the web server redirects everything to the Legacy. Further, every client-side stored data (cookies, local databases, and so on) that refers to Proxy URL are translated between Client and Original server by the Apache Reverse Proxy.

My opinion

Client side integrations that involves data manipulation!? It sounds weird to me. So, in my humble opinion, Siebel JDB and Siebel EAI (Web services) are the best options to integrate Legacy applications with Siebel. And even when client-side interactions are needed, we can easily mix it with SWE API (invoking simple interactions within the URL) or isolating one of the presented solutions only for these interactions.

PS.: Sorry about my bad english…

Thats all, folks! :) See you later…

Deixe uma resposta

O seu endereço de email não será publicado Campos obrigatórios são marcados *

Você pode usar estas tags e atributos de HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>