Events

The EventsPlugIn is a TokenPlugIn that works as an extension to execute a server side environment based on events and different to the native jWebSocket environment. The classic plug-ins and filters now are implemented differently and appears new observable” objects based on the Observable Pattern. The C2S/S2C communication based on tokens is replaced by C2S/S2C events notifications”.

The main differences with the current jWebSocket base environment are:

  • Spring framework integration.
  • Based on an event-driven model using the observable pattern.
  • The filters are focus on support aspects related to events notifications, are executed in chain before and after every C2S event notification.
  • Plug-ins offer support to related events in the server side, using different methods signature and not only the unique processToken” method.

Example:

public void processEvent(Logon aEvent, WebSocketResponseEvent aResponseEvent);
public void processEvent(Logoff aEvent, WebSocketResponseEvent aResponseEvent);

Event-Driven paradigm

"In computer programming, event-driven programming or event-based programming is a programming paradigm in which the flow of the program is determined by events—i.e., sensor outputs or user actions (mouse clicks, key presses) or messages from other programs or threads. Event-driven programming can also be defined as an application architecture technique in which the application has a main loop which is clearly divided down to two sections: the first is event selection (or event detection), and the second is event handling..." >>

How it works?

The EventsPlugIn process incoming tokens with the "_IS_EM_"(Is event model?) flag in TRUE, after a new Event is generated that represents the token type, for example a token type:"auth.logon" is mapped to a Logon event class instance, after that the "events" workflow starts.

Events workflow:

So if you are familiar with event-driven programming, are looking for a decouple and flexible environment, this plug-in will be very useful for you.

Why the observable pattern?

The Observable Pattern defines one-to-many dependency between objects so that when object changes state, all its dependents are notified and updated automatically. Solve the need to maintain consistency between related objects without making classes tightly coupled. Generally guarantee clean implementations, high flexibility and less dependency between objects.

The Observer Pattern implementation in the EventsPlugIn is done using a Map, so the access to the listeners is very fast. Consider every listener loaded in memory and ready to use in terms of time needed to get a response” versus the classic way for RPC calls where the classes must be loaded, instances created, many other checks needed to execute the targeted method, etc…

The principal disadvantage is the memory consumption in systems with a lot of listeners.

The IObservable interface

  • void on(Collection aEventClassCollection, IListener aListener) throws Exception;
  • void on(Class aEventClass, IListener aListener) throws Exception;
  • void addEvents(Class aEventClass);
  • void addEvents(Collection aEventClassCollection);
  • void removeEvents(Class aEventClass);
  • void removeEvents(Collection aEventClassCollection);
  • void un(Class aEventClass, IListener aListener);
  • void un(Collection aEventClassCollection, IListener aListener);
  • ResponseEvent notify(Event aEvent, ResponseEvent aResponseEvent, boolean useThreads) throws Exception;
  • ResponseEvent notifyUntil(Event aEvent, ResponseEvent aResponseEvent) throws Exception;
  • boolean hasListeners(Class aEventClass) throws Exception;
  • boolean hasListener(Class aEventClass, IListener aListener) throws Exception;
  • void purgeListeners();
  • void purgeEvents();
  • boolean hasEvent(Class aEventClass);

Filters

A filter is a piece of code executed before/after every client event notification. Many filters are used to handle the aspects related to events. In the EventsPlugIn the filters are observable objects too, are very similar to the jWebSocket native filters, but this are focus on events filtering” versus tokens filtering”.

API:

void beforeCall(WebSocketConnector aConnector, WebSocketEvent aEvent) throws Exception {}
void afterCall(WebSocketConnector aConnector, WebSocketResponseEvent aEvent) throws Exception {}

For example the ValidatorFilter checks that the notified event match with all the restrictions defined in it definition. The capacity to check incoming and outgoing arguments without wire code in the listeners keeps clean the implementation. The validation process ensures that the server listeners only receive events with valid information and the client always receives the response that he is waiting for. In fact the validation process is a kind of permanent functional tests” for C2S calls.

The event definition

An event definition is a clean way to describe attributes, aspects and restrictions related to external events (from the client). Is used to get information in runtime and control the events workflow. Filters use the events definitions to handle the aspects related to its.

Supported aspects by filters are:

  • Routing:

    In the before call this filter checks if the incoming event has listeners, if not the workflow finish in that point. In the second call this filter sends the response to targeted connectors.

  • Security:

    Checks if the authenticated user has the required roles to notify an event. If not, the listener’s notification is not authorized.

  • Cache:

    In the first call this filter checks is a non-expired response event is cached for the incoming event, if exists, the cached response is sent to the client. In the second call the response event is stored in cache if required to.

  • Validation:

    This filter checks if every defined incoming/outgoing arguments math the validation rules associated to its.

  • Annotation:

    This filter process custom annotations in Event instances.

Current WebSocketEventDefinition attributes:



Attribute Description
String id The token type. Example: auth.logon”
String ns Class location representing the token type. Example: org.jwebsocket.eventmodel.event.auth.Logon”
Set<Argument> incomingArgsValidation Description of the incoming arguments in the notified event
Set<Argument> outgoingArgsValidation Description of the outgoing arguments in the response event
Boolean responseRequired Indicates if an event require response to the client. Default value is false
Boolean responseToOwnerConnector Indicates if the same client that fires the event is waiting for the response. Default value is false
Boolean notificationConcurrent Indicates if the listeners can be notified concurrently or using a simple iteration. Default value is false
Boolean cacheEnabled Indicates if the cache aspect is enabled for an event. Default value is false
Integer cacheTime Time used to store in cache the response event.
Boolean securityEnabled Indicates if the security aspect is enabled for an event. Default value is false
Set<String> roles Roles restrictions to allow an event notification. Example: !USER, all”
Set<String> ipAddresses IP addresses restrictions to allow an event notification. Example: !66.66.66.1/254, all”
Set<String> users Users restrictions to allow an event notification. Example: user1, user2, userN”

Event definition example (Logon event) using the Spring IOC:


  
  
  
  
  
    
      
        
        
        
      
      
        
        
        
      
    
  
  
    
      
        
        
        
      
      
        
        
        
      
    
  

The class WebSocketEventDefinition can be extended if needed for custom scenarios, new aspects support, etc…

The Logon class definition:

public class Logon extends WebSocketEvent {

  @ImportFromToken
  private String username;

  @ImportFromToken
  private String password;
  ...
  //Getters and Setters
  ...

Spring Integration

Integrated spring components in the EventsPlugIn:

  • IOC Container: Inversion of Control (IOC) is a style of software construction where reusable generic code controls the execution of problem-specific code. It carries the strong connotation that the reusable code and the problem-specific code are developed independently, which often results in a single integrated application. Inversion of Control as a design guideline serves the following purposes:
    • There is a decoupling of the execution of a certain task from implementation.
    • Every system can focus on what it is designed for.
    • The systems make no assumptions about what other systems do or should do.
    • Replacing systems will have no side effect on other systems.
  • Security: Spring Security provides comprehensive security services for J2EE-based enterprise software applications. There is a particular emphasis on supporting projects built using The Spring Framework, which is the leading J2EE solution for enterprise software development.”
  • Validation: There are pros and cons for considering validation as business logic, and Spring offers a design for validation (and data binding) that does not exclude either one of them. Specifically validation should not be tied to the web tier, should be easy to localize and it should be possible to plug in any validator available. Considering the above, Spring has come up with a Validator interface that is both basic and eminently usable in every layer of an application.

The uses of Spring is highly recommended to get a server side environment that includes database support, transactions, AOP and more features.

Core Components

At the lower level, the plug-in only require four components to work: EventModel, EventFactory, EventsDefinitionManager, RouterFilter and the S2CEventNotificationHandler. The EventsPlugIn's backbone is the EventModel singleton object that is in fact an ObservableObject; it receives incoming events from the client, executes the filters and notifies the listeners (generally plug-ins). Uses the EventFactory to map the raw Token to an Event instance, the EventsDefinitionManager provides the events definitions needed to.

The RouterFilter is who finally send response to the clients.

The S2CEventNotificationHandler is the component to handle the s2c event notifications. Store the callbacks used to handle the client response.

Plug-Ins

The plug-ins are extensions to support custom events in the server side. Basically are listeners listening related events.

For example the authentication plug-in listen Logon and Logoff events.

The plug-ins has the capacity to define its client API, this is used by the SystemPlugIn to export to clients the server side plug-ins API. API exporting for plug-ins is like WSDL in web services, in fact the JavaScript support use it to create a client side representation of the server side plug-ins.

See the API exported information:

{"api":{
  "logon":{
    "outgoingArgsValidation":[
      {"optional":false,"name":"username","type":"string"},
      {"optional":false,"name":"roles","type":"array"}
    ],
    "isSecurityEnabled":false,
    "roles":[],
    "users":[],
    "ip_addresses":[],
    "cacheTime":0,
    "incomingArgsValidation":[
      {"optional":false,"name":"username","type":"string"},
      {"optional":false,"name":"password","type":"string"}
    ],
    "type":"auth.logon",
    "isCacheEnabled":false
  },
  "logoff":{
    "outgoingArgsValidation":[],
    "isSecurityEnabled":true,
    "roles":["USER"],
    "cacheTime":0,
    "incomingArgsValidation":[],
    "type":"auth.logoff",
    "isCacheEnabled":false
  }
}}

Server side authentication plug-in code example:

public class AuthPlugIn extends EventModelPlugIn {

  private AuthenticationManager am;

  public void processEvent(Logon aEvent, WebSocketResponseEvent aResponseEvent) {
    //Login process
    Authentication request = new UsernamePasswordAuthenticationToken(
    aEvent.getUsername(), aEvent.getPassword());
    Authentication result = getAm().authenticate(request);
    SecurityContextHolder.getContext().setAuthentication(result);

    //Setting the username
    aEvent.getConnector().setUsername(aEvent.getUsername());

    //Adding roles in the response
    FastList<String> roles = new FastList<String>();
    for (GrantedAuthority ga :
    SecurityContextHolder.getContext().getAuthentication().getAuthorities()) {
      roles.add(ga.getAuthority());
    }
    aResponseEvent.getArgs().setString("username", aEvent.getUsername());
    aResponseEvent.getArgs().setList("roles", roles);
    aResponseEvent.setMessage(">> Login process has finished successfully!");
  }

  public void processEvent(Logoff aEvent, WebSocketResponseEvent aResponseEvent) {
    SecurityContextHolder.clearContext();
    //Removing username value
    aEvent.getConnector().setUsername(null);

    aResponseEvent.setMessage("<< Logout process has finished successfully!");
  }
  :

Plug-in configuration:


  
  
  
    
      
      
    
  

JavaScript support

The EventsPlugIn’s JavaScript support offer to web-developers an excellent integration with the server side plug-ins, the main features are:

  • New OnResponse callback object to allow more detailed treatment for responses:
{
  OnResponse: function(aResponseEvent){ },
  OnSuccess: function(aResponseEvent){ },
  OnFailure: function(aResponseEvent){ },
}
  • Client filters to support aspects in the client side for any outgoing/incoming event notification, following the same server configuration. Cache, Security and Validation aspects are supported. Filters in the client guarantee lower consumption of network’s bandwidth and saves unnecessary processing on the server side.
  • Automatic generation of server plug-ins as JavaScript objects in runtime using the remote plug-ins API. A generated plug-in appears like this:
authPlugIn.logon({
  args: {
    username: “some username”,
    password: “some password”
  },
  OnSuccess: function(aResponseEvent){
    //Do something when logon successfully
  }
});
authPlugIn.logoff();

How to setup the client environment?

  // Creating the filter chain
  securityFilter = new jws.SecurityFilter();
  securityFilter.user = {username: "", roles: []};

  cacheFilter = new jws.CacheFilter();
  cacheFilter.cache = new jws.cache.Cache();

  validatorFiler = new jws.ValidatorFilter();

  // Creating a event notifier instance
  notifier = new jws.EventsNotifier();
  notifier.jwsClient = jws.myConn; //A native jWebSocket client
  notifier.filterChain = [securityFilter, cacheFilter, validatorFiler];
  notifier.initialize();

  // Creating a plug-in generator instance
  generator = new jws.EventsPlugInGenerator();

  // Generating the auth plug-in and using the OnReady callback to finish the object definition
  auth = generator.generate("auth", notifier, function(){
    // The generation process is finished
    // Add other method here if needed
  }
Publications

Learn more about WebSockets in general, get background information and gain deeper insight!

Join jWebSocket

Wether developer, designer or translator – join the jWebSocket team and grow together with our success!

Contact

jWebSocket Headquarter

Innotrade GmbH

An Vieslapp 29

52134 Herzogenrath

Germany

Search

Copyright © 2013 Innotrade GmbH. All rights reserved.