Understanding the Home Subscriber Server (HSS) Sh interface
How WebLogic SIP Server Works
This section examines how easy is to use the API included in the current release of WLSS to communicate with an HSS server.
WLSS profile API
The DIAMETER Sh interface is exposed as a Provider, and the container will take care of all DIAMETER behaviors. For a developer, WebLogic SIP Server provides an interface
com.bea.wcp.profile.ProfileService whose implementation is registered in the servlet context, and can be used for easily retrieving the profile. The helper class returns the user data as an XML document, and the developer can use standard DOM techniques to work on it. In the case of the Sh Pull Update command, the
ProfileService will always return the user data as read-only documents, so you have to explicitly clone it before modifying it. Regarding the Sh Profile Update request, the application can specify a
ProfileListener class to be notified of incoming messages from the HSS. Thanks to the converged container you can query the HSS no matter which channel is currently being used, HTTP or SIP.
Building a simple Sh Request
Building an Sh request is pretty simple. An Sh request always follow this schema:
protocol://uri/reference_type/access_key
Where:
- protocol is obviously sh
- uri usually is a Public User Identity or a User Identity
- reference_type specifies the data reference type requested
- access_key corresponds to the value of the Attribute-Value Pair (AVP)
These are some examples of Document Selector Elements for Sh Data Request:
- Requesting data related to service IM2SMS (where IM2MS represents a ServiceIndication):
sh://sip:username@domain.com/RepositoryData/IM2SMS - Requesting public identity related to username@domain:
sh://sip:username@domain.com/IMSPublicIdentity/ - Requesting MSISDN:
sh://sip:username@domain.com/MSISDN/
Retrieving the ServiceProfile
In an HTTP or SIP servlet, the very first thing to do is to import
com.bea.wcp.profile.ProfileService. In the
init() method a reference to the
ProfileService is stored for retrieving data from the HSS. This code snippet shows how to do this:
public void init() throws ServletException
{
ServletContext sc = getServletContext();
// Get the ProfileService from the ServletContext
ps = (ProfileService)
sc.getAttribute(ProfileService.PROFILE_SERVICE);
if (ps == null)
{
throw new ServletException("Profile service not found");
}
System.out.println(getClass().getName() + " initialized");
}
Preparing the Sh Request String
It's easy to execute an Sh Pull request in WLSS. The example below shows how to build an Sh Request String, based on the request type using a switch statement:
public static String buildShRequest( int requestType,
String userName, String ServiceName, int domainType,
String serverName )
{
String docSelector = "sh://sip:";
// Get username
docSelector += userName;
// Matching RequestType with Data reference
switch(requestType)
{
case Constants.SH_REPOSITORY_DATA:
docSelector += "/RepositoryData/" + ServiceName;
break;
case Constants.SH_MSISDN:
docSelector += "/MSISDN/";
break;
case Constants.SH_IMS_PUBLIC_IDENTITY:
docSelector += "/IMSPublicIdentity/";
break;
case Constants.SH_CHARGING_INFO:
docSelector += "/ChargingInformation/";
break;
case Constants.SH_USER_STATE:
docSelector += "/UserState/";
docSelector += (domainType==Constants.SH_PS_DOMAIN)?"PS-Domain/":"CS-Domain/";
break;
case Constants.SH_IMS_USER_STATE:
docSelector += "/IMSUserState/";
break;
case Constants.SH_S_CSCF_NAME:
docSelector += "/S-CSCFName/";
break;
case Constants.SH_INITIAL_FILTER_CRITERIA:
docSelector += "/InitialFilterCriteria/" + serverName;
break;
case Constants.SH_LOCATION_INFO:
docSelector += "/LocationInformation/";
docSelector += (domainType == Constants.SH_PS_DOMAIN)? "PS-Domain/":"CS-Domain/";
break;
}
}
Executing an Sh Pull
Now we're going to execute an Sh Pull request in WebLogic SIP Server. In this example we're requesting a RepositoryData, so we need to get extra information beyond the user. You need the service name. After building the Sh request we pass it to the ProfileService previously instantiated:
private String executeTest(String theShRequest)
{
String response = null;
try {
logger.debug("Sh Request: " + theShRequest );
// Get the document from the HSS
Document genericDoc = ps.getDocument(theShRequest);
response = DIAMETERHelper.toString(genericDoc.getDocumentElement());
logger.debug("HSS Response: \n" + response);
} catch (ProfileException e) {
// Get the Message Exception
MessageException me = (MessageException)e.getCause();
// Get the DIAMETER ResultCode
ResultCode rc = me.getResultCode();
session.setAttribute(Constants.DIAMETER_RESULT_CODE, rc.toString());
session.setAttribute("Exception", e.getMessage());
logger.debug("Exception - DIAMETER Result Code is: " + rc.toString() );
} catch (Exception e) {
response = e.getMessage();
session.setAttribute("Exception", e.getMessage());
logger.debug("Exception: " + response);
}
return response;
}
Executing an Sh Pull update
After receiving the data from the HSS using Sh Pull, it's now possible to modify it using the standard DOM techniques. Saving the new data is simple: All you have to do is clone the document received previously (because
ProfileServer returns a read-only document) and then call the method
put() exposed by the
ProfileServer, as shown here:
private String executeTest(String theShRequest, String newData,
String newValue)
{
String response = null;
try {
logger.debug("Sh Request: " + theShRequest );
Document originalDoc = ps.getDocument(theShRequest);
// Preparing to modify the document
logger.debug("Going to prepare document");
// Modifying original document
Document modifiedDocument = this.saveDoc(
(Document)originalDoc.cloneNode(true),newData, newValue);
// Storing using Profile
ps.putDocument(theShRequest, modifiedDocument);
logger.debug("Saving data into HSS");
// Store in session the SIP SH Output Request
session.setAttribute(Constants.SIPAS_OUTPUT,
DIAMETERHelper.toString(modifiedDocument));
response = DIAMETERHelper.toString(
originalDoc.getDocumentElement());
logger.debug("HSS Response: \n " + response);
} catch (ProfileException e) {
MessageException me = (MessageException)e.getCause();
ResultCode rc = me.getResultCode();
session.setAttribute(Constants.DIAMETER_RESULT_CODE,
rc.toString());
session.setAttribute("Exception", e.getMessage());
logger.debug("Exception - DIAMETER Result Code is: " +
rc.toString() );
} catch (Exception e) {
response = e.getMessage();
session.setAttribute("Exception", e.getMessage());
logger.debug("Exception: " + response);
}
return response;
}