JBoss.orgCommunity Documentation

Chapter 2. Resource Adaptor Type

2.1. Activities
2.2. Events
2.3. Activity Context Interface Factory
2.4. Resource Adaptor Interface
2.5. Restrictions
2.6. Sbb Code Examples

Diameter CCA Resource Adaptor Type is defined by Mobicents team as part of effort to standarize RA Types.

Diameter CCA Type 2.6.0-SNAPSHOT defines two types of activities:

net.java.slee.resource.diameter.cca.CreditControlClientSession

This type of activity represents client side of credit control session. It is a source of answers to credit control requests issued with this activity. It is also source of re-authentication requests.

This activity type can be created with call to one of methods of CreditControlProvider. It ends once underlying credit control session ends. State machine for client credit control can be found here and here .

net.java.slee.resource.diameter.cca.CreditControlServerSession

This type of activity represents server side of credit control session. It is source of credit control requests issued from client side and answers to re-auth requests.

This activity type is created explicitly for incoming requests by Resource Adaptor. It ends once underlying credit control session ends. State machine for server credit control can be found here and here

Both activities define methods required to properly function and expose necessary information to JSLEE services. Common part for each is defined as follows:




        public CreditControlSessionState getState();
        public String getSessionId();
        public CreditControlAVPFactory getCCAAvpFactory();
        public CreditControlMessageFactory getCCAMessageFactory();
    
    
CreditControlSessionState getState();

returns current state of credit control session. State directly follows definition from credit control rfc .

String getSessionId();

returns session Id of underlying diameter session.

CreditControlAVPFactory getCCAAvpFactory()

returns AVP factory capable of creating specifc AVPs for credit control. It also exposes means of accessing base AVP factory.

CreditControlMessageFactory getCCAMessageFactory();

returns message factory capable of creating credit control messages. It also exposes means of accessing base factory.

Client type activity interface is defined as follows:




       CreditControlRequest createCreditControlRequest();
       void sendCreditControlRequest(CreditControlRequest ccr) throws IOException;
       void sendInitialCreditControlRequest(CreditControlRequest ccr) throws IOException;
       void sendReAuthAnswer(ReAuthAnswer rar) throws IOException;
       void sendUpdateCreditControlRequest(CreditControlRequest ccr) throws IOException;
       void sendTerminationCreditControlRequest(CreditControlRequest ccr) throws IOException;
    
CreditControlRequest createCreditControlRequest();

Creates credit control request for this activity. Fills AVPs appropriate for this session..

void sendCreditControlRequest(CreditControlRequest ccr) throws IOException;

sends credit control request, does not perform any other operations.

void sendInitialCreditControlRequest(CreditControlRequest ccr) throws IOException;

sends credit control request. Ensures that its initial request by setting proper AVP .

void sendUpdateCreditControlRequest(CreditControlRequest ccr) throws IOException;

sends credit control request. Ensures that its update request by setting proper AVP .

void sendTerminationCreditControlRequest(CreditControlRequest ccr) throws IOException;

sends credit control request. Ensures that its termination request by setting proper AVP .

void sendReAuthAnswer(ReAuthAnswer rar) throws IOException;

sends re-authentication answer on this session.

Server type activity interface is defined as follows:



    
      CreditControlAnswer createCreditControlAnswer();
      void sendCreditControlAnswer(CreditControlAnswer cca) throws IOException;
      void sendReAuthRequest(ReAuthRequest rar) throws IOException;
    
    
    
CreditControlAnswer createCreditControlAnswer();

creates credit control answer for last received request.

void sendCreditControlAnswer(CreditControlAnswer cca) throws IOException;

sends credit control answer through this session.

void sendReAuthRequest(ReAuthRequest rar) throws IOException;

sends re-authentication request through this session.

Note

It is safe to type cast activities to interface defined in Base RA Type: net.java.slee.resource.diameter.base.DiameterActivity

Credit Control declares only two additional events, to those defined in Base RA Type, namely CreditControlAnswer and CreditControlRequest. However, it also reuses Base events.




Important

Spaces where introduced in Name and Class column values, to correctly render the table. Please remove them when using copy/paste.

Activity context interface factory is defined as follows:




package net.java.slee.resource.diameter.cca;
import javax.slee.ActivityContextInterface;
public interface CreditControlActivityContextInterfaceFactory {
  public ActivityContextInterface getActivityContextInterface(CreditControlClientSession cccs);
  public ActivityContextInterface getActivityContextInterface(CreditControlServerSession ccss);
}
    
    

Resource Adaptor SBB Interface provides SBBs with means of accessing RA objects required for interaction in DIAMETER world. It is defined as follows:



    
    package net.java.slee.resource.diameter.cca;
    import net.java.slee.resource.diameter.base.CreateActivityException;
    import net.java.slee.resource.diameter.base.events.avp.DiameterIdentity;
    public interface CreditControlProvider {
      CreditControlClientSession createClientSession() throws CreateActivityException;
      CreditControlClientSession createClientSession(DiameterIdentity destinationHost, 
        DiameterIdentity destinationRealm) throws CreateActivityException;
      CreditControlMessageFactory getCreditControlMessageFactory();
      CreditControlAVPFactory getCreditControlAVPFactory();
      int getPeerCount();
      DiameterIdentity[] getConnectedPeers();
    }
    

Current Resource Adaptor Type has no defined restrictions.

Simple client side requesting credits, with EVENT_TYPE credit control request:




private void doSendEventCCR(int currencyCode,int value) {
    try {
        //Create session.
        CreditControlClientSession session = this.provider.createClientSession();
        ActivityContextInterface localACI = this.acif.getActivityContextInterface(session);
        localACI.attach(this.getSbbContext().getSbbLocalObject());
        CreditControlRequest request = session.createCreditControlRequest();
    
        List<DiameterAvp> avps = new ArrayList<DiameterAvp>();
 
        avps.add(avpFactory.getBaseFactory().createAvp(Avp.ORIGIN_HOST, 
            ("aaa://" + originIP + ":" + originPort).getBytes()));
        avps.add(avpFactory.getBaseFactory().createAvp(Avp.ORIGIN_REALM, 
            originRealm.getBytes()));
        //or dedicated:
        //request.setDestinationHost(destinationHost);
        //request.setDestinationRealm(destinationRealm);
        avps.add(avpFactory.getBaseFactory().createAvp(Avp.DESTINATION_HOST, 
            ("aaa://" + destinationIP + ":" + destinationPort).getBytes()));
        avps.add(avpFactory.getBaseFactory().createAvp(Avp.DESTINATION_REALM, 
            destinationRealm.getBytes()));
        //Event Type request has request type set to '4'
        avps.add(avpFactory.getBaseFactory().createAvp(
            CreditControlAVPCodes.CC_Request_Type, 4l));
        avps.add(avpFactory.getBaseFactory().createAvp(
            CreditControlAVPCodes.CC_Request_Number, 0l));
            RequestedServiceUnitAvp rsu = this.avpFactory.createRequestedServiceUnit();
            CcMoneyAvp ccMoney = this.avpFactory.createCcMoney();
        ccMoney.setCurrencyCode(currencyCode);
        UnitValueAvp unitValue = this.avpFactory.createUnitValue();
        unitValue.setValueDigits(value);
        ccMoney.setUnitValue(unitValue);
        
        rsu.setCreditControlMoneyAvp(ccMoney);
            avps.add(rsu);
            avps.add(avpFactory.getBaseFactory().createAvp(
            CreditControlAVPCodes.Requested_Action, 0));
        //use extension avps to fill message or dedicated setters/getters
        request.setExtensionAvps(avps.toArray(new DiameterAvp[avps.size()]));
        // Now create and send
        
        if (logger.isInfoEnabled())
            logger.info("About to send:\n" + request);
            session.sendCreditControlRequest(request);
    } catch (Exception e) {
        logger.error("Failed to create/send Credit-Control-Request.", e);
    }
}
    
    
    ....
    
    public void onCreditControlAnswer(CreditControlAnswer answer, ActivityContextInterface aci) {
        logger.info("Received CCA with Result-Code[" + answer.getResultCode() + "].");
        switch (answer.getCcRequestType().getValue()) {
        case 1:
        case 2:
        case 3:
            logger.error("Received 'session' credit control answer. Expecting EVENT_TYPE answer");
            break;
        case 4:
            //result code 2xxx is success
            if(answer.getResultCode()/1000 == 2 )
            {
                //assume msg is correct
                GrantedServiceUnitAvp gsu = answer.getGrantedServiceUnit();
                CcMoneyAvp money = gsu.getCreditControlMoneyAvp();
                doSpendMoney(money);
            }else
            {
                //error, this will pring formated msg dump.
                logger.warn("Result of CC operation is a failure:\n"+answer);
            }
            break;      
        }
    } 
    

Server application to handle simple direct debiting:



public void onCreditControlRequest(CreditControlRequest request, 
    ActivityContextInterface aci) {
    if (logger.isInfoEnabled())
        logger.info("Received Credit-Control-Request (Application-Id[" + request.getHeader().getApplicationId() + "].");
    // INITIAL_REQUEST(1), UPDATE_REQUEST(2), TERMINATION_REQUEST(3),
    // EVENT_REQUEST(4)
    CreditControlServerSession session = (CreditControlServerSession) aci.getActivity();
    CreditControlAnswer answer = null;
    if(request.getRequestedAction() == RequestedActionType.DIRECT_DEBITING)
    {
    
        switch (request.getCcRequestType().getValue()) {
        case 1:
            try {
                if (logger.isInfoEnabled())
                    logger.info("Got INITIAL_REQUEST(1).");
                if (getSentInitialAnswer()) {
                    logger.error("Error. Initial answer already sent! Aborting.");
                    return;
                }
                
                answer = session.createCreditControlAnswer();
                if(userHasCredit(request.getUserName(),request.getRequestedServiceUnit()))
                {
                    GrantedServiceUnitAvp gsu = chargeUser(request.getRequestedServiceUnit());
                    answer.setGrantedServiceUnit(gsu);
                    answer.setResultCode(2001);
                }else
                {
                    //4012 == CREDIT_LIMIT_REACHED
                    answer.setResultCode(4012);
                }
                if (logger.isInfoEnabled()) {
                    logger.info("Processed Credit-Control-Request:\n" + request);
                    logger.info("Sending Credit-Control-Answer:\n" + answer);
                }
                session.sendCreditControlAnswer(answer);
                this.setSentInitialAnswer(true);
            } catch (Exception e) {
                logger.error("Failed to create/send Credit-Control-Answer to reply INITIAL_REQUEST(1).", e);
            }
            break;
        case 2:
            try {
                if (logger.isInfoEnabled())
                    logger.info("Got UPDATE_REQUEST(2).");
                if (getSentUpdateAnswer()) {
                    logger.error("Error. Update answer already sent! Aborting.");
                    return;
                }
                answer = session.createCreditControlAnswer();
                if(userHasCredit(request.getUserName(),request.getRequestedServiceUnit()))
                {
                    GrantedServiceUnitAvp gsu = chargeUser(request.getRequestedServiceUnit());
                    answer.setGrantedServiceUnit(gsu);
                    answer.setResultCode(2001);
                }else
                {
                    //4012 == CREDIT_LIMIT_REACHED
                    answer.setResultCode(4012);
                }
                if (logger.isInfoEnabled()) {
                    logger.info("Processed Credit-Control-Request:\n" + request);
                    logger.info("Sending Credit-Control-Answer:\n" + answer);
                }
                session.sendCreditControlAnswer(answer);
                setSentUpdateAnswer(true);
            } catch (Exception e) {
                logger.error("Failed to create/send Credit-Control-Answer to reply UPDATE_REQUEST(2).", e);
            }
            break;
        case 3:
            try {
                if (logger.isInfoEnabled())
                    logger.info("Got TERMINATION_REQUEST(3).");
                if (getSentTerminationAnswer()) {
                    logger.error("Error. Termination answer already sent! Aborting.");
                    return;
                }
                answer = session.createCreditControlAnswer();
                if(userHasCredit(request.getUserName(),request.getRequestedServiceUnit()))
                {
                    GrantedServiceUnitAvp gsu = chargeUser(request.getRequestedServiceUnit());
                    answer.setGrantedServiceUnit(gsu);
                    answer.setResultCode(2001);
                }else
                {
                    //4012 == CREDIT_LIMIT_REACHED
                    answer.setResultCode(4012);
                }
                if (logger.isInfoEnabled()) {
                    logger.info("Processed Credit-Control-Request:\n" + request);
                    logger.info("Sending Credit-Control-Answer:\n" + answer);
                }
                session.sendCreditControlAnswer(answer);
                setSentTerminationAnswer(true);
            } catch (Exception e) {
                logger.error("Failed to create/send Credit-Control-Answer to reply TERMINATION_REQUEST(3).", e);
            }
            break;
        case 4:
            try {
                if (logger.isInfoEnabled())
                    logger.info("Got EVENT_REQUEST(4).");
                answer = session.createCreditControlAnswer();
                if(userHasCredit(request.getUserName(),request.getRequestedServiceUnit()))
                {
                    GrantedServiceUnitAvp gsu = chargeUser(request.getRequestedServiceUnit());
                    answer.setGrantedServiceUnit(gsu);
                    answer.setResultCode(2001);
                }else
                {
                    //4012 == CREDIT_LIMIT_REACHED
                    answer.setResultCode(4012);
                }
                if (logger.isInfoEnabled())
                    logger.info("Sending Credit-Control-Answer:\n" + answer);
                session.sendCreditControlAnswer(answer);
            } catch (Exception e) {
                logger.error("Failed to create/send Credit-Control-Answer to reply EVENT_REQUEST(4).", e);
            }
            break;
        default:
            logger.error("Unexpected CC-Request-Type in message: " + request.getCcRequestType() + ". Aborting...");
        }
        }else
        {
            answer = session.createCreditControlAnswer();
            //4011 == DIAMETER_CREDIT_CONTROL_NOT_APPLICABLE
            answer.setResultCode(4011);
            session.sendCreditControlAnswer(answer);
        }
    }