How to build an IM (XMPP) solution with Oracle APEX and Websockets

0

Using Kaazing Websocket Gateway and OpenFire

Scenario:
If you, for example, have a webshop and a webshop online support application for internal use, this solution will let the webshop customer call in some help by using IM. The support application will react on the customer call by opening the support application with customer details selected and the messaging client opened.
I used an Apex application to create both parts of the solution. The IM client however is easy to integrate in any kind of website/framework.

 

Underneath the recipe for some nice IM functionality in Oracle Apex, assuming you have a running Apex instance and a JVM 1.5+ install) and moderate+ Apex skills:
  1. Scrape together the ingredients
  2. Install Kaazing Gateway XMPP edition and OpenFire
  3. Configure Kaazing and OpenFire
  4. Create an Apex app with IM client
  5. Create anApex Webshop support app
  6. Wire the Apex Webshop support app to the Apex app with IM client
  7. Final touch
After finishing this step-by-step recipe your application looks like this:
The webshop support app (page content is depending on your one creativity)

The webshop side of the scenario without the shop :-):

Scrape together the ingredients

I build my demo app on a Oracle Linux but Kaazing and OpenFire are also available on Windows. You can download them from the following webpage: kaazing xmpp-edition. Choose the package suitable for your OS and select the one including documentation and demo’s. OpenFire is also included in this downloaded package.


All the other files you need are in the zip file you can download from this link: imdemo. Place the whole zipped directory into the images directory of your Apex instance.

Installing Kaazing and OpenFire

Installing the software can be done by unzipping the downloaded file in the directory of your choice. After that the the directory looks like this:

Ready to configure!!!

Configuration of Kaazing

This is really easy. The config file of the websocket gateway is located in <your kaazing home dir>\conf\gateway-config.xml and by default configured listening to localhost on port 8000. You only have to change the cross-site-constraint property to http://localhost:8080 to allow requests from Apex. You can test your ‘install’ by starting the server (<your kaazing home dir>\bin\gateway.start) and navigate in the browser to http://localhost:8000/index.html. The config for this demo (based on localhost only) should like this:

 

 

If you want to go beyond localhost, edit the config file according to your network configuration. The gateway will start on every ip/port you define. For example to make the service visible from outside the localhost you should define an accept service on the assigned ip adress of the network card. Without this the service isn’t visible from the outside. Besides this you can configure cross-site-constraints for restricting acces to the service. Take a look at the admin guide available on the url provided.

Configuring OpenFire

OpenFire is a real time collaboration (RTC) server licensed under the Open Source Apache License. It uses the only widely adopted open protocol for instant messaging, XMPP (also called Jabber). For more details take a look at openFire.

To test your ‘install’ of OpenFire start the server (<your openfire home dir>\bin\openfire.start) and check the admin page on http://localhost:9090 (default). You can log in with admin/welcome1. By default the OpenFire server is preconfigured with a HSQL database. If you don’t have a real database maybe a good choice. As an APEX fan you want this running on Oracle! To fix this little problem you have to run the setup of OpenFire. This can be done by editing the openfire.xml located in <your openfire home dir>\conf.

 

 

Locate the setup element and replace true with false. It isn’t necessary to change the connectionProvider. The setup will handle this. Before you can continue you have to do the following:

First create a database schema with a name of your choice. Run the Oracle DDL script located in <your openfire home dir>\resources\database as the user you created. Also copy an ojdbc6.jar (or ojdbc5.jar depending on your JVM version) to <your openfire home dir>\lib directory. Now restart the server (openfire.stop and openfire start) and open the admin page again. Now a setup appears.

 

Click next and enter a name of the domain of your choice (something like xmpp.demo.com) and click continue. Check as database setting Standard Database Connection and click continue. Fill the database connection settings according to your running database and user you created before. Complete the rest of the setup and login to the admin page to review the server settings.

Watch out!!!! After the fresh setup the admin password has changed to admin.

Everything is now prepared to cook the webshop online support application!!!

Create the Apex app with IM client

Create an Apex application with settings of your choice with one empty page. Following the next steps:

Step 1

Create an application item PASSWORD to store the password. We need this to ‘single sign on’ to the IM service. Change the login proces on your login page so the password is stored in this application item:

APEX_UTIL.SET_SESSION_STATE(‘PASSWORD’, :P101_PASSWORD);

 

Step 2

Add some HTML to the HTML header part of your empty page:

<meta content=”http://localhost:8080/apex/i/imdemo/resources/PostMessageBridge.html” name=”kaazing:postMessageBridgeURL”>

<link rel=”stylesheet” href=”#IMAGE_PREFIX#imdemo/resources/css/demo.css” />

<script type=”text/javascript” src=”#IMAGE_PREFIX#imdemo/resources/js/enterprise.js”></script>

<script type=”text/javascript” src=”#IMAGE_PREFIX#imdemo/resources/js/deployJava.js”></script>

<script src=”#IMAGE_PREFIX#imdemo/resources/js/WebSocket.js”></script>

<script src=”#IMAGE_PREFIX#imdemo/resources/js/XmppClient.js”></script>

<script src=”#IMAGE_PREFIX#imdemo/resources/js/Drag.js”></script>

<script src=”#IMAGE_PREFIX#imdemo/resources/js/imDemoClient.js”></script>

 

I think the meta content element isn’t necessary for this local host demo. You can find some explanation in the admin guide about this.

 

Step 3

Create a HTML text region on the page with the following HTML. This will be the a floating div containing the IM client:

<div id=”chat_roster”>

<div id=”rosterStatus” style=”visibility:visible”>

<div id=”roster”></div>

<div id=”setAvailability”>

<div style=”margin:0px 0px 2px 5px;”><span>My status: </span>

<select onChange=”gui_setStatus()” id=”availability” style=”position:relative; margin-left: 2px; width:100px”>

<option value=”available”>Available</option>

<option value=”away”>Away</option>

<option value=”dnd”>Do Not Disturb</option>

</select>

</div>

</div>

<div id=”setStatus”>

<div style=”margin:0px 0px 2px 5px;”>

<span>My note: </span>

<input type=”text” value=”On Web Chat” id=”status” onBlur=”gui_setStatus()”  style=”position:relative; padding:0px; margin-left: 2px; width:100px”/>

</div>

</div>

</div>

</div>

<div id=”FloatingChat” style=”visibility:hidden”>

<div id=”Chat” style=”position:absolute; z-index:10; left:800px; top:160px; width:400px;background-color:#bfdcf0; border:1px solid #0E76BC;”>

<div style=”padding-bottom:8px; width:400px; background-color:#0E76BC; border-bottom:1px solid #0E76BC;” onMouseDown=”beginDrag(this.parentNode, event);”>

<div style=”position:absolute; top:2px; left:5px; font-size:16px; font-weight:bold; color:#FFFFFF;”>Chat</div>

<div style=”position:absolute; top:3px; left:377px; float:right;” onClick=”this.parentNode.parentNode.style.display = ‘none’;”>

</div>

</div>

<br/>

<div>

<div style=”float: left; width: 390px;” id=”chat_messages”>

<div id=”chatWindow” style=”visibility:hidden”>

<div id=”chatText” style=”background-color:#FFFFFF;”>

<div style=”height:100%”></div>

</div>

<div>

<div style=”margin:0px 0px 5px 0px;”>

<span>

<div id=”chat” style=”font-size:14px; color:#0E76BC;”></div>

<div id=”sentTo” style=”visibility:hidden”></div>

</span>

</div>

<input type=”text” id=”typing” value=”” readonly=”readonly” style=”visibility:hidden”/>

<input type=”text” onKeyPress=”gui_enterSend(this,event); gui_typing(event);” style=”width:99%; height:auto;”/>

</div>

</div>

</div>

<br/>

<div>

<img src=”#IMAGE_PREFIX#imdemo/resources/images/application-exit-4.png” width=”15″ height=”15″ style=”position: absolute; top: 0; right: 0;” onclick=”closeChat()”>

</div>

</div>

</div>

<div>

<object id=”beep3″ type=”audio/wav” style=”visibility:hidden;” data=”#IMAGE_PREFIX#imdemo/resources/sound/ahem.wav”>

<param name=”autostart” value=”false” />

</object>

</div>

 

Step 4

Create a dynamic action on the resource load event of the region you have created and add some javascript code:

 

var appuser = “&APP_USER.”;

var password = “&PASSWORD.”;

setup(appuser.toLowerCase(), password);

openChat();

 

Step 5

Create a HTML region next to the region from step 3. In this region the wired customer support app will open up.

 

In the region source put the following:

 

<form>

<input type=”checkbox” id=”openApp” />Open lineked app?

</form>

 

We need this later to play around. Give the region the static id : imdemoAppRegion.

Important!!! The linked app will be opened up as an child (iframe) of this region. So the id of the region must be exactly the same.

 

Step 6

In order to be able to open other applicaions in an iframe without login again you have to:

Add a cookie name to your authentication schema and call it IMDEMO. Under security attributes set browser security/embed in frames to Allow from same origin.

 

Create the Apex Webshop support app

You can implement functionality of your choice inside this application. The only condition is the starting point of the application. The IM client app will open this application in an iframe with one url parameter : the username of the calling/called customer. You have to use this parameter to select/filter the data in the application or initial set other attributes. My customer support app consists of a tab and page with name and adress details of the customer and a tab/page with order history.

 

Step 1

Set the same cookie name as described in step 6 and make sure you use the same authentication schema as the Apex app with IM client. Under security attributes set browser security/embed in frames to Allow from same origin.

Step 2

Create 3 application items to store data to communicate with the Apex app with IM client. You have to use exactly the same name as below:

  • CHKURL
  • CUSTOMER (use session state protection – checksum on session level)
  • URL

Create and application process with a process point on demand and call it URL_CHKSM. Put the following code inside:

 

DECLARE

l_url varchar2(2000);

BEGIN

select APEX_UTIL.PREPARE_URL(

p_url => :URL,

p_checksum_type => ‘SESSION’) into l_url from dual;

:CHKURL := nvl(l_url,:P_URL);

htp.prn(:CHKURL);

END;

 

This will be used to add the checksum to the url generated by javascript on the Apex app with IM client side and parse the CUSTOMER value.

 

Step 3

You now can create one or more pages with data selection/filtering based on the CUSTOMER application item. Don’t forget to set security/page acces protection, on the first page you want to open from the IM client, to Arguments Must Have Checksum.

 

You are now ready to wire the Apex app with IM client with the Apex Webshop support app.

Wire the apps

The wiring can be done via the imDemoClient.js from the zip file.You only have to set the following values at the top of the file:

 

var linkedApp = <your webshop support app id goes here>;

var linkedAppPage = <your webshop support app first page id goes here>;

 

Do not close the file. You have to change more!!

Final touch

In order to let the Apex IM client communicate with the openFire server change to following variable value in the imDemoClient.js file.

 

var jid = “<put you servername here>”;

 

Replace <put you servername here> with the servername you choose as OpenFire server name. The server name can also be found at the servertab of the OpenFire admin console. Look under the part Server properties. You can can now testrun the application. If everything was done right your page should look like this:

 

The error message is shown because we haven’t created a user in OpenFire.

Create OpenFire users

You can create users with the admin console. Don’t forget: the username and password of the OpenFire user should match exactly with the Apex user. Now reload the Apex page and the error won’t popup again and the left page looks like this:

 

Check the admin console of OpenFire. You should see a session running for the user.

Now it’s time to create someone to talk to. Create a new Apex/OpenFire user. To see each other as contact you also have to create a group in OpenFire and add both users to the group. This looks like this:

 

Don’t forget to check Enable contact list group sharing. Save your changes and reload the Apex page. The new user should appear in Contact with status offline.

Now it’s time for some real messaging action!

Start two different browsers with the Apex app with IM client and the now linked support app (to prevent unwanted sharing of sessions, for example firefox and chrome) and log in with both users. The user who is acting like the customer support should check the checkbox with prompt Open linked app? to get the right response. The user who is acting like the online webshop user calling for help, should not. If the online webshop user clicks in the contactlist a chatwindow will popup. Start typing and on the other side the customer support app will react with opening the app with customer details and chatwindow.

Some other tips

  • If you browse the OpenFire database schema you can see user and group tables. Adding users and groups can also be done by inserting directly into the database.
  • You can also connect to OpenfFire with, for example, the Spark IM Client
  • It is also possible to build a room to chat with more people at the same time

 

Share.

About Author

Leave a Reply