JBoss.orgCommunity Documentation

Chapter 4. Source Code Overview

4.1. Rules Source
4.2. JMX Source
4.3. SLEE Service Source
4.3.1. Service descriptor
4.3.2. SLEE Library

Important

To obtain the application's complete source code please refer to Section 2.2, “Mobicents JAIN SLEE USSD Gateway Application Source Code”.

This chapter explains how components perform their tasks. For more detailed explanation of JSLEE related source code and xml descriptors, please refer to simple examples, like sip-wakeup. Also for detailed description of rules source code please refer to Drools documentation

USSD Gateway Application makes use of Drools as rules engine.

Engine is configured with DRL files. DRL file contains set of rules which perform operations on facts passed into engine. USSD Gateway Application DRL file defines rules to match initial USSD string to set of values identifying protocol and address of peer to which messages should be forwarded. Rule file name is USSDGateway.drl. File content looks as follows:



package org.mobicents.ussdgateway.rules
1
import org.mobicents.ussdgateway.rules.Call;
2
rule "USSDGateway1"
    
3
    when
        $c : Call( ussdString == "*123#" )
    then
4
        $c.setSip( true );
        $c.setSipProxy( "192.168.0.101" );
        $c.setSipTo("123");
        $c.setSipPort(5060);
5
end
    
    

1

import of fact POJO

2

definition of rule

3

condition to enter rule clause. It accesses fact property ussdString and matches it against #123* value, if it matches engine jumps to then part

4

rule part which sets defined SIP peer as destination for messages

5

end of USSDGateway1 rule

Rules are fed with facts on which engine performs matching operations(in general). Facts are simple POJO classes. This applications fact looks as follows:



package org.mobicents.ussdgateway.rules;
import java.io.Serializable;
/**
 * Acts as Fact for Rules
 * @author amit bhayani
 *
 */
public class Call implements Serializable {
    //Initial string, its like #123*
    private String ussdString;
    
    private boolean isSip;
    private boolean isHttp;
    private boolean isSmpp;
    
    private String sipProxy;
    private String sipTo;
    private int sipPort;
    
    //to be used with other protocols
    private String genericUrl;
    
    public Call(String ussdString){
        this.ussdString = ussdString;
    }
    public String getUssdString() {
        return ussdString;
    }
    public boolean isSip() {
        return isSip;
    }
    public void setSip(boolean isSip) {
        this.isSip = isSip;
    }
    public boolean isHttp() {
        return isHttp;
    }
    public void setHttp(boolean isHttp) {
        this.isHttp = isHttp;
    }
    public boolean isSmpp() {
        return isSmpp;
    }
    public void setSmpp(boolean isSmpp) {
        this.isSmpp = isSmpp;
    }
    public String getSipProxy() {
        return sipProxy;
    }
    public void setSipProxy(String sipProxy) {
        this.sipProxy = sipProxy;
    }
    public String getSipTo() {
        return sipTo;
    }
    public void setSipTo(String sipTo) {
        this.sipTo = sipTo;
    }
    public int getSipPort() {
        return sipPort;
    }
    public void setSipPort(int sipPort) {
        this.sipPort = sipPort;
    }
    /**
     * @return the genericUrl
     */
    public String getGenericUrl() {
        return genericUrl;
    }
    /**
     * @param genericUrl the genericUrl to set
     */
    public void setGenericUrl(String genericUrl) {
        this.genericUrl = genericUrl;
    }
    
}
    
                

JMX part of USSD Gateway Application is responsible for initiating rules engine and exposing management methods. Single JMX bean is defined with XML descriptor file jboss-beans.xml. Descriptor content looks as follows:



<?xml version="1.0" encoding="UTF-8"?>

<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
    xmlns="urn:jboss:bean-deployer:2.0">

    <bean name="RulesService" class="org.mobicents.ussdgateway.rules.RulesService">
        <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(
            name="org.mobicents.ussdgateway:service=RulesService"
            ,exposedInterface=org.mobicents.ussdgateway.rules.RulesServiceMBean.class
            ,registerDirectly=true)
        </annotation>
    </bean>
</deployment>
    
    

JMX interface is defined as follows:



package org.mobicents.ussdgateway.rules;
import javax.naming.NamingException;
/**
 * 
 * @author amit bhayani
 *
 */
public interface RulesServiceMBean  extends org.jboss.system.ServiceMBean {
    
1
    String getJndiName();
    void setJndiName(String jndiName) throws NamingException;
    
    
2
    void startService() throws Exception;
    void stopService() throws Exception;
}
    
    

It defines following:

1

management method. This method controls JNDI name under which rule engine is made available to SLEE Service

2

regular lifecycle methods

Implementation of above interface fulfills defined contracts in following way:

void startService() throws Exception



public void startService() throws Exception {
1
        setupRule();
2
        rebind();
        
        this.logger.info("Started Rules Service");
}
private void setupRule() {
3
        Resource resource = ResourceFactory.newUrlResource(CHANGESET_FILE_PATH);
4
        kagent = KnowledgeAgentFactory.newKnowledgeAgent("UssdGatewayAgent");
        kagent.applyChangeSet(resource);
        ResourceFactory.getResourceChangeNotifierService().start();
        ResourceFactory.getResourceChangeScannerService().start();
}
private void rebind() throws NamingException {
        InitialContext rootCtx = new InitialContext();
        // Get the parent context into which we are to bind
        Name fullName = rootCtx.getNameParser("").parse(jndiName);
        System.out.println("fullName=" + fullName);
        Name parentName = fullName;
        if (fullName.size() > 1)
            parentName = fullName.getPrefix(fullName.size() - 1);
        else
            parentName = new CompositeName();
        Context parentCtx = createContext(rootCtx, parentName);
        Name atomName = fullName.getSuffix(fullName.size() - 1);
        String atom = atomName.get(0);
        NonSerializableFactory.rebind(parentCtx, atom, kagent);
}
private static Context createContext(Context rootContext, Name name)
            throws NamingException {
        Context subctx = rootContext;
        for (int n = 0; n < name.size(); n++) {
            String atom = name.get(n);
            try {
                Object obj = subctx.lookup(atom);
                subctx = (Context) obj;
            } catch (NamingException e) { // No binding exists, create a
                // subcontext
                subctx = subctx.createSubcontext(atom);
            }
        }
        return subctx;
}
            
            

1

load rules into engine

2

bind rule engine to specified JNDI name

3

load ChangeSet as rule resource

4

create rule engine and initiate it

void stopService() throws Exception



    public void stopService() throws Exception {
    
1
        unbind(jndiName);
    }
            
            

1

unbind rule engine from JNDI

void setJndiName(String jndiName) throws NamingException



public void setJndiName(String jndiName) throws NamingException {
    
1
        String oldName = this.jndiName;
        this.jndiName = jndiName;
        
2
        if (getState() == STARTED) {
            unbind(oldName);
            try {
                rebind();
            } catch (Exception e) {
                NamingException ne = new NamingException(
                        "Failed to update jndiName");
                ne.setRootCause(e);
                throw ne;
            }
        }
    }
            
            

1

set property and retain old value

1

rebind rule engine in JNDI in case bean is running

JMX bean loads change set file USSDGatewayChangeSet.xml. This file controls how rules set is loaded and maintained by rule engine. Please refer to Section 2.4, “Rule engine configuration” for details.

Since there is no standard defined for communication between USSD gateway and service providing peers, Mobicents USSD Gateway Application defines its own standard for encoding.

This SLEE library contains all classes required to properly encode and decode messages exchanged between Mobicents USSD Gateway and service providing peers. Library itself is built on top of JAXB framework.

Standard is defined with single XSD file ussd.xsd. This file defines three types of encoded data:

Library classes are plain JAXB POJOs. They are marshalled to XML form in standard way:



import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.mobicents.ussdgateway.ObjectFactory;
import org.mobicents.ussdgateway.USSDAbort;
import org.mobicents.ussdgateway.USSDRequest;
import org.mobicents.ussdgateway.USSDResponse;
JAXBContext jAXBContext = JAXBContext.newInstance("org.mobicents.ussdgateway");
ObjectFactory objectFactory = new ObjectFactory();
USSDRequest req = this.objectFactory.createUSSDRequest();
req.setInvokeId(1);
req.setUssdCoding(0xFF);
req.setUssdString("#112*");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
JAXBElement<USSDRequest> jxb = this.objectFactory.createRequest(req);
jAXBContext.createMarshaller().marshal(jxb, bos);
String xmlRequest = new String(bos.toByteArray());
Unmarshaller um = this.jAXBContext.createUnmarshaller();
JAXBElement o = (JAXBElement) um
        .unmarshal(new ByteArrayInputStream(xmlRequest));
if (o.getDeclaredType().equals(USSDRequest.class)) {
    //do something
} else if (o.getDeclaredType().equals(USSDResponse.class)) {
    //do something
} else if (o.getDeclaredType().equals(USSDAbort.class)) {
    //do something
}
        

In SLEE components library is referenced as follows:



<library-ref>
    <library-name>library-ussdgateway</library-name>
    <library-vendor>org.mobicents</library-vendor>
    <library-version>2.0</library-version>
</library-ref>