Sei sulla pagina 1di 12

App Server Architecture

1. Introduction
NextGen NMS, or OmniVista 4.1.1, is a network management system. NG NMS uses
AngularJS as framework at client side and uses Spring as framework at server side.
Server
(Service-Based)

Client
(Web-Based)

HTML5 + CSS3

JSON
REST

AngularJS

Spring MVC
MOM
(Message-Oriented Middleware)

Spring Core + Context

MongoDB
Headless Client (OV Client)

RMI

OV 2500
At server side, we have 3 important components: AppServer, Framework and
Services.
-

AppServer: Contains a Spring MVC implementation to listen to requests from


client. Then it will send requests to services layer for real processing. This
component also contains Mongo Framework.
Services: This component contains the services implementation such as:
licensing, discovery, access guardian
Framework: Is the framework code (library code) , it is used by services and
appserver. In other words, framework doesnt have any service.

2. App Server Architecture

APP Server

Requests

DB

Controllers

Controllers will expose the REST APIs so that web GUI can request or set data.
We will base on Spring MVC component and Servlet 3 for this purpose. An
example API look like:
@RequestMapping(method = RequestMethod.GET, value = "/licenses",
produces="application/json")
@ResponseBody
public DeferredResult<NGServerResponse> getLicenses(HttpServletRequest
request, HttpServletResponse response){
DeferredResult<NGServerResponse> dr = new
DeferredResult<NGServerResponse>();
ServiceRequest<String> serviceRequest = new ServiceRequest<String>();
serviceRequest.setOperation(NGServerUtils.READ_ALL);
serviceRequest.setServiceName(NGServerUtils.getServiceName
(request.getRequestURL()));
serviceRequest.setRequestType(NGServerUtils.ASYNC_SINGLE);
serviceRequest.setTarget(TARGET_PROCESSOR);
m_processor.processAsyncRequest(dr, serviceRequest);
return dr;
}

Each service will choose these mechanisms for its processing:


Synchronous request: the code flow will be locked until it receives a response.
This mechanism is usually used for DB access.
Asynchronous-Single request: the code flow is not locked. This mechanism is
used to listen to result from another service and the result is a single object.
Asynchronous-Multi request: the code flow is not locked. The response is
separated to many parts.

3. Adding a new service


3.1. Synchronous Service
Below are steps to implement a sync service in app server:

GUI

- Result is NGServerResponse type

- Listen to requests with POST/PUT/GET type.


- Call RequestProcessor.processSyncRequest method

Controller

Base on the service name (registered on the context file), it will c


- Result is NGServerResponse- type
- Dont implement this. This class belongs to App Server framewor

RequestProcessor

- Result is ServiceResponse type

ISyncService

- Implement processRequest m

3.1.1.Controller Implementation
Introduce your own controller class in com.alu.ov.ngnms.appserver.controller
package. Below is an example GET method:
@Autowired
private IRequestProcessor m_processor;
/****************Sync*****************/
@RequestMapping(method = RequestMethod.GET, value = "/syncexample")
@ResponseBody
public NGServerResponse getExample(HttpServletRequest request,
HttpServletResponse response) {
ServiceRequest<ObjectExample> serviceRequest = new
ServiceRequest<ObjectExample>();
serviceRequest.setOperation(NGServerUtils.READ_ALL);
serviceRequest.setServiceName(NGServerUtils.getServiceName(
request.getRequestURL()));
NGServerResponse sr = m_processor.processSyncRequest(serviceRequest);
return sr;
}

Notes:

Define the processor variable for process request calling (IRequestProcessor,


implementation class is RequestProcessor, we already have a bean in the
application context file).
To prepare data, you need to initialize the ServiceRequest instance with:
o Operation: READ_ALL, UPDATE, DELETE
o Service name: if your controller has the URL is /syncexample, the
service name will be syncexample. You just call
NGServerUtil.getServiceName(request.getRequestURL()).
After preparing data, just call processSyncRequest method to process request
and get the response.

3.1.2.Implement synchronous service


We have an interface called ISyncService. You need to implement your own
service with this interface. Then register your service to request processor (using
applicationContext.xml file):
<property name="synchServiceMap">
<map>
<entry key="unps" value-ref="syncUNPService" />
<entry key="locator" value-ref="syncLocatorService" />
<entry key="syncexample" value-ref="syncExampleService" />
</map>
</property>
<bean id="syncExampleService"
class="com.alu.ov.ngnms.serviceclient.SyncExampleServiceImpl" />

An example for SyncService Implementation:


@Autowired
private SyncExampleMessageProcessor syncExampleMessageProcessor;
@Override
public ServiceResponse processRequest(ServiceRequest serviceRequest) {
ServiceResponse<ObjectExample> serviceResponses = new
ServiceResponse<ObjectExample>();
try {
serviceResponses =
syncExampleMessageProcessor.processMessage(serviceRequest);
} catch (NgnmsServiceException e) {
serviceResponses.setRequestType(serviceRequest.getRequestType());
}
return serviceResponses;
}

3.2.

Asynchronous Single Response Service

GUI
- Listen to requests with POST/PUT/GET type.
- Call RequestProcessor.processAsyncRequest method to p
- Result is DeferredResult type

Controller

- Base on the service name (registered on the context file), it will call to
- Dont implement this. This class belongs to App Server framework.
- Call processResponse method.
RequestProcessor

- Call onMessage method

- Implement this interface.


IAsyncService
- Initialize IMessageListener variable.
- Execute MessageListener.postRequest to proces

- Get ITargetMessageProcessor in targetMap based on target property (register


- Dont implement this interface. The app server framework already implemen
- Call postResponse method.

IMessageListener

Implement this interface.


Call IMessageListener.postResponse method to res
ITargetMessageProcessor

3.2.1.Controller
- Initialize IRequestProcessor variable to call processASyncRequest function of
RequestProcessor class.
- Initialize ServiceRequest variable and set its properties.
- Initialize DeferredResult variable to store received result.
- Example:
private static final String TARGET_PROCESSOR = "exampleMessageProcessor";
@Autowired
private IRequestProcessor m_processor;

@RequestMapping(method = RequestMethod.GET, value = "/example",


roduces="application/json")
@ResponseBody
public DeferredResult<NGServerResponse> get1Example(HttpServletRequest request,
ttpServletResponse response){
DeferredResult<NGServerResponse> dr = new
DeferredResult<NGServerResponse>();
ServiceRequest<String> serviceRequest = new ServiceRequest<String>();
serviceRequest.setOperation(NGServerUtils.READ_ALL);
serviceRequest.setServiceName(NGServerUtils.getServiceName(
quest.getRequestURL()));
serviceRequest.setRequestType(NGServerUtils.ASYNC_SINGLE);
serviceRequest.setTarget(TARGET_PROCESSOR);
m_processor.processAsyncRequest(dr, serviceRequest);
return dr;
}

3.2.2.IAsyncService Implementation
We have to implement 2 methods: processRequest and onMessage. In
processRequest method, we call MessageListener.postRequest to post the request
to processor. Inside onMessage method we call RequestProcessor.processResponse
to send the result to the client.
private IRequestProcessor m_requestProcessor;
private IMessageListener m_messageListener;
public AsyncExampleServiceImpl(IRequestProcessor requestProcessor,
IMessageListener messageListener){
m_requestProcessor = requestProcessor;
m_messageListener = messageListener;
}
@Override
public void processRequest(ServiceRequest serviceRequest)
throws NgnmsServiceException {
m_messageListener.postRequest(serviceRequest);
}
@Override
public void onMessage(ServiceResponse serviceResponse)
throws NgnmsServiceException {

m_requestProcessor.processResponse(serviceResponse);
}

After implementing IAsyncService, we register this object to the


RequestProcessor with a service name (match with the URL of this
service controller):
<bean id="requestProcessor"
class="com.alu.ov.ngnms.appserver.processor.RequestProcessor">
<property name="asynchServiceMap">
<map>
<entry key="example" value-ref="asyncexampleService" />
</map>
</property>
</bean>
<bean id="map" class="java.util.HashMap" scope="prototype" >
<constructor-arg>
<map>
<entry key="example" value-ref="asyncexampleService" />
</map>
</constructor-arg>
</bean>
<bean id="asyncexampleService"
class="com.alu.ov.ngnms.serviceclient.AsyncExampleServiceImpl">
<constructor-arg ref="requestProcessor"/>
<constructor-arg ref="messageListener"/>
</bean>

3.2.3.ITargetMessageProcessor implementation
You have to implement the processMessage method to process the request and
build the result to send back to the client.
public void processMessage(ServiceRequest serviceRequest) throws
NgnmsServiceException;

After you have the result, you need to use MessageListener to send the
response. An example:
ServiceResponse<String> result = new ServiceResponse<String>();
result.setCorrelationID(requestContent.getRequestID());
result.setFinal(true);
result.setRequestType(requestContent.getRequestType());
result.setServiceName(requestContent.getServiceName());
String data = "";
Object status = response.getProperty(ExampleResponseType.STATUS);
if (status != null && "success".equals(String.valueOf(status))) {
try {
data = response.getBody(new TypeReference<String>() {});
} catch (NGMessagingException e) {

NGLogger.error(LOGGER, "Error while processing the response", e);


}
result.setData(data);
try {
m_mesageListener.postResponse(result);
} catch (NgnmsServiceException e) {
NGLogger.error(LOGGER, "Could not post the response.", e);
}

After implementing, register your message processor to the message


listener using applicationContext.xml file:
<bean id="targetMap" class="java.util.HashMap" scope="prototype" >
<constructor-arg>
<map>
<entry key="exampleMessageProcessor"
value-ref="exampleMessageProcessor" />
</map>
</constructor-arg>
</bean>

Note: the key string must match with the target string in
ServiceRequest object (see Controller).
3.3. Asynchronous Multiple Responses Service
The code flow is same with Asynchronous Single Response Service. We have some
differences:
3.3.1.Controller
Instead of using DeferedResult to post the response, we use AsyncContext of
Servlet:
private static final String TARGET_PROCESSOR = "exampleMessageProcessor";
@Autowired
private IRequestProcessor m_processor;
@RequestMapping(method = RequestMethod.GET, value = "/examples",
produces="application/json")
@ResponseBody
public void get2Example(HttpServletRequest request, HttpServletResponse response){
AsyncContext asyncContext = request.startAsync(request, response);
ServiceRequest<String> serviceRequest = new ServiceRequest<String>();
serviceRequest.setOperation(NGServerUtils.READ_ALL);
serviceRequest.setServiceName(NGServerUtils.getServiceName(
request.getRequestURL()));
serviceRequest.setRequestType(NGServerUtils.ASYNC_MULTI);
serviceRequest.setTarget(TARGET_PROCESSOR);
}

m_processor.processAsyncRequest(asyncContext, serviceRequest);

3.3.2.ITargetMessageProcessor Implementation
Because we have multiple parts, we need to set a flag to the ServiceResponse
object so that the client can determine a part is final or not. For example:
ServiceResponse<String> result = new ServiceResponse<String>();
result.setData(ngMessagePart.getBody(new TypeReference<String>(){}));
result.setCorrelationID(requestContent.getRequestID());
result.setRequestType(requestContent.getRequestType());
result.setServiceName(requestContent.getServiceName());
if (result.getData().equals("49")) {
result.setFinal(true);
} else {
result.setFinal(false);
}
m_mesageListener.postResponse(result);

4. Using Messaging to communicate requests


NextGen NMS uses Messaging Framework to communicate data between the
applications. We can understand Messaging Framework is Message-Oriented
Middleware:

To use messaging in your service, please see the attached doc.

GuideLine-Messaging
Framework.docx

Potrebbero piacerti anche