OSB Reporting Action Extension

This article focuses on extending the OSB reporting action feature by making the reporting data accessible outside OSB Dashboard.


EduSagar - OSB Reporting Action Extension 1

EduSagar - OSB Reporting Action Extension 2

By default a reporting action in OSB proxy service flow will show the report in OSB dashboard.

When reporting action is invoked in proxy service it publishes the report message to an internal queue wli.reporting.jmsprovider.queue from where an application (JMS Reporting Provider) reads this message and publishes it to the OSB dashboard.

This behavior can be extended so that the same message (ReportMessage object) is published to one more queue ensuring the default behavior remains intact and also gives developer a flexibility to leverage this message for more efficient monitoring and reporting purposes

Implementation steps to extend OSB reporting action


1. Create a connection factory and queue on OSB server, managed or admin depending on the configuration, where the copy of report messages will be sent
a. Create below JMS connection factory and JMS Queue in any JMS Module (I created a new one)
i. Connection Factory -  jms/TestConnectionFactory
ii. Queue - jms/TestJMSQueue

2. Create a simple Java Project and add below libraries in the project dependency section
a. <OSB_HOME>\lib\modules\com.bea.alsb.reporting.api.jar
b. <OSB_HOME>\lib\modules\com.bea.alsb.reporting.impl.jar
c. wlserver_10.3\server\lib\weblogic.jar

3. Add the attached java files to this project under reporting package
a. CustomJmsReportingStartupAndShutdown This class is activated when a custom MDB(explained later) gets started and adds a ReportingDataHandler to ReportingDataManager

Download this JAVA File

package reporting;

import com.bea.wli.reporting.ReportingDataManager;

import javax.jms.JMSException;

import javax.naming.NamingException;

import weblogic.application.ApplicationException;
import weblogic.application.ApplicationLifecycleEvent;
import weblogic.application.ApplicationLifecycleListener;


public class CustomJmsReportingStartupAndShutdown extends ApplicationLifecycleListener
{
private static ReportingDataManager _manager;
private CustomReportingDataHandler _jmsHandler;

public CustomJmsReportingStartupAndShutdown() {
super();
this._jmsHandler = null;
}

public void preStart(final ApplicationLifecycleEvent evt) throws ApplicationException {
}

public void postStart(final ApplicationLifecycleEvent evt) throws ApplicationException {
try {
CustomJmsReportingStartupAndShutdown._manager = ReportingDataManager.getManager();
CustomJmsReportingStartupAndShutdown.this._jmsHandler = new CustomReportingDataHandler();
CustomJmsReportingStartupAndShutdown._manager.addHandler(CustomJmsReportingStartupAndShutdown.this._jmsHandler);
}
catch (NamingException e) {
e.printStackTrace();
throw new ApplicationException(e.getCause());
} catch (JMSException e) {
e.printStackTrace();
throw new ApplicationException(e.getCause());
}
}

public void preStop(final ApplicationLifecycleEvent evt) throws ApplicationException {
try {
CustomJmsReportingStartupAndShutdown.this._jmsHandler.close();
CustomJmsReportingStartupAndShutdown._manager.removeHandler(CustomJmsReportingStartupAndShutdown.this._jmsHandler);

}
catch (Exception e){
e.printStackTrace();
throw new ApplicationException(e.getCause());
}
}

public void postStop(final ApplicationLifecycleEvent evt) {
}

static {
CustomJmsReportingStartupAndShutdown._manager = null;
}
}


b. CustomReportingDataHandler This class receives events from the reporting action and publishes them to our demo queue (jms/TestJMSQueue) 

Download this JAVA File

package reporting;

import com.bea.wli.reporting.MessagecontextDocument;
import com.bea.wli.reporting.ReportingDataHandler;
import com.bea.wli.reporting.jmsprovider.runtime.ReportMessage;
import com.bea.wli.reporting.jmsprovider.utils.ReportingUtil;

import java.io.InputStream;
import java.io.Serializable;

import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlTokenSource;


public class CustomReportingDataHandler implements ReportingDataHandler
{

private final static String JMS_CON_FACTORY = "jms/TestConnectionFactory";
private final static String JMS_QUEUE = "jms/TestJMSQueue";
private Queue reportingQ;
private QueueConnectionFactory qConFactory;

public CustomReportingDataHandler() throws NamingException, JMSException {
super();
System.out.println("Inside CustomReportingDataHandler Constructor");
Context ic = new InitialContext();
try {
System.out.println("Doing lookup for custom ConnectionFactory/ReportingQueue");
qConFactory = (QueueConnectionFactory)ic.lookup(JMS_CON_FACTORY);
reportingQ = (Queue)ic.lookup(JMS_QUEUE);
} catch (NamingException ne){
if (ic != null) {
try {
ic.close();
} catch (NamingException ex) {
ex.printStackTrace();
throw ex;
}
}
}
}

public void handle(final XmlObject metadata, final String s) throws Exception {
System.out.println("Inside Method 1");
if (metadata instanceof MessagecontextDocument) {
final ReportMessage msg = new ReportMessage(metadata, s);
this.processDataBeforeSending(metadata, msg, 1);
}
}

public void handle(final XmlObject metadata, final InputStream is) throws Exception {
System.out.println("Inside Method 2");
if (metadata instanceof MessagecontextDocument) {
final byte[] bindata = ReportingUtil.copyInputStreamtoByteArray(is);
final ReportMessage msg = new ReportMessage(metadata, bindata);
this.processDataBeforeSending(metadata, msg, 3);
}
}

public void handle(final XmlObject metadata, final XmlObject data) throws Exception {
System.out.println("Inside Method 3");
if (metadata instanceof MessagecontextDocument) {
final ReportMessage msg = new ReportMessage(metadata, data);
this.processDataBeforeSending(metadata, msg, 2);
}
}

public void handle(final XmlObject metadata, final XmlTokenSource data) throws Exception {
throw new UnsupportedOperationException();
}

public void handle(final XmlObject metadata, final Serializable data) throws Exception {
throw new UnsupportedOperationException();
}

public void close() {
}

public void flush() {
}

private void processDataBeforeSending(final XmlObject metadata, final ReportMessage msg, final int dataType) throws Exception {
System.out.println("Inside Method 4");
Thread t = new Thread(new MessagePublisher(this, msg, dataType));
t.start();
System.out.println("Leaving Method ");
}


private class MessagePublisher implements Runnable{

private CustomReportingDataHandler dataHandler;
private ReportMessage msg;
private int dataType;

public MessagePublisher(CustomReportingDataHandler dataHandler, ReportMessage msg, int dataType){
this.dataHandler = dataHandler;
this.msg = msg;
this.dataType = dataType;
}

public void run(){
QueueConnection qcon = null;
QueueSession qsession = null;
QueueSender qsender = null;
try {
qcon = dataHandler.qConFactory.createQueueConnection();
qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
qsender = qsession.createSender(dataHandler.reportingQ);
final ObjectMessage message = qsession.createObjectMessage();
message.setIntProperty("MSGTYPE", 1);
message.setIntProperty("REPORTINGDATATYPE", dataType);
message.setObject(msg);
qsender.send(message);
} catch (JMSException e) {
e.printStackTrace();
} finally{
if (qsender != null) {
try {
qsender.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
if (qsession != null) {
try {
qsession.close();
}
catch (Exception ex2) {
ex2.printStackTrace();
}
}
if (qcon != null) {
try {
qcon.close();
}
catch (Exception ex3) {
ex3.printStackTrace();
}
}
}
}
}
}


4. Create a jar of this project and copy it to <DOMAIN_HOME>\lib folder.  Download this JAR file for testing purpose


5. For testing purpose create a simple MDB to read from the demo queue (jms/TestJMSQueue) and print the payload. The message published into Queue is a ReportMessage object and contains payload and the metadata (as available in OSB dashboard)

6. Download the sample MDB project containing OSBReportingMDBBean MDB that reads from the queue and prints the payload into server logs.


7. Deploy this MDB to OSB Managed Server. Once the MDB gets started it will instantiate the CustomJmsReportingStartupAndShutdown class for further action.

Download the EAR file.

Feel free to provide your feedback..

- Prabodh Mitra
comments powered by Disqus