Showing posts with label IndyJug. Show all posts
Showing posts with label IndyJug. Show all posts

Saturday, July 19, 2014

Tailing a file - Spring Websocket sample

This is a sample that I have wanted to try for sometime - A Websocket application to tail the contents of a file.


The following is the final view of the web-application:



There are a few parts to this application:

Generating a File to tail:


I chose to use a set of 100 random quotes as a source of the file content, every few seconds the application generates a quote and writes this quote to the temporary file. Spring Integration is used for wiring this flow for writing the contents to the file:

<int:channel id="toFileChannel"/>

<int:inbound-channel-adapter ref="randomQuoteGenerator" method="generateQuote" channel="toFileChannel">
	<int:poller fixed-delay="2000"/>
</int:inbound-channel-adapter>

<int:chain input-channel="toFileChannel">
	<int:header-enricher>
		<int:header name="file_name" value="quotes.txt"/>
	</int:header-enricher>
	<int-file:outbound-channel-adapter directory="#{systemProperties['java.io.tmpdir']}" mode="APPEND" />
</int:chain>

Just a quick note, Spring Integration flows can now also be written using a Java Based DSL, and this flow using Java is available here

Tailing the file and sending the content to a broker


The actual tailing of the file itself can be accomplished by OS specific tail command or by using a library like Apache Commons IO. Again in my case I decided to use Spring Integration which provides Inbound channel adapters to tail a file purely using configuration, this flow looks like this:
<int:channel id="toTopicChannel"/>

<int-file:tail-inbound-channel-adapter id="fileInboundChannelAdapter"
				channel="toTopicChannel"
				file="#{systemProperties['java.io.tmpdir']}/quotes.txt"
				delay="2000"
				file-delay="10000"/>

<int:outbound-channel-adapter ref="fileContentRecordingService" method="sendLinesToTopic" channel="toTopicChannel"/>
and its working Java equivalent

There is a reference to a "fileContentRecordingService" above, this is the component which will direct the lines of the file to a place where the Websocket client will subscribe to.

Websocket server configuration

Spring Websocket support makes it super simple to write a Websocket based application, in this instance the entire working configuration is the following:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketDefaultConfig extends AbstractWebSocketMessageBrokerConfigurer {

	@Override
	public void configureMessageBroker(MessageBrokerRegistry config) {
		//config.enableStompBrokerRelay("/topic/", "/queue/");
		config.enableSimpleBroker("/topic/", "/queue/");
		config.setApplicationDestinationPrefixes("/app");
	}

	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		registry.addEndpoint("/tailfilesep").withSockJS();
	}
}

This may seem a little over the top, but what these few lines of configuration does is very powerful and the configuration can be better understood by going through the reference here. In brief, it sets up a websocket endpoint at '/tailfileep' uri, this endpoint is enhanced with SockJS support, Stomp is used as a sub-protocol, endpoints `/topic` and `/queue` is configured to a real broker like RabbitMQ or ActiveMQ but in this specific to an in-memory one.

Going back to the "fileContentRecordingService" once more, this component essentially takes the line of the file and sends it this in-memory broker, SimpMessagingTemplate facilitates this wiring:

public class FileContentRecordingService {
	@Autowired
	private SimpMessagingTemplate simpMessagingTemplate;

	public void sendLinesToTopic(String line) {
		this.simpMessagingTemplate.convertAndSend("/topic/tailfiles", line);
	}
}


Websocket UI configuration

The UI is angularjs based, the client controller is set up this way and internally uses the javascript libraries for sockjs and stomp support:

var tailFilesApp = angular.module("tailFilesApp",[]);

tailFilesApp.controller("TailFilesCtrl", function ($scope) {
    function init() {
        $scope.buffer = new CircularBuffer(20);
    }

    $scope.initSockets = function() {
        $scope.socket={};
        $scope.socket.client = new SockJS("/tailfilesep);
        $scope.socket.stomp = Stomp.over($scope.socket.client);
        $scope.socket.stomp.connect({}, function() {
            $scope.socket.stomp.subscribe("/topic/tailfiles", $scope.notify);
        });
        $scope.socket.client.onclose = $scope.reconnect;
    };

    $scope.notify = function(message) {
        $scope.$apply(function() {
            $scope.buffer.add(angular.fromJson(message.body));
        });
    };

    $scope.reconnect = function() {
        setTimeout($scope.initSockets, 10000);
    };

    init();
    $scope.initSockets();
});

The meat of this code is the "notify" function which the callback acting on the messages from the server, in this instance the new lines coming into the file and showing it in a textarea.


This wraps up the entire application to tail a file. A complete working sample without any external dependencies is available at this github location, instructions to start it up is also available at that location.

Conclusion

Spring Websockets provides a concise way to create Websocket based applications, this sample provides a good demonstration of this support. I had presented on this topic recently at my local JUG (IndyJUG) and a deck with the presentation is available here

Wednesday, June 27, 2012

Spring Integration presentation at IndyJUG

I spoke on Spring Integration and Enterprise Integration patterns at the IndyJUG today. I thought the presentation was well received and I got some very good questions from the audience.

Here is my presentation:



And the sample project to go with the presentation: https://sites.google.com/site/bkscriptssite/home/scripts/sidemoproject.zip

Wednesday, May 30, 2012

IndyJUG - Session on SOLID principles

Today I attended a session on SOLID Object Oriented Principles at Indianapolis JUG(Indy JUG), the talk was by Matt Stine.

The talk was a very good aggregation of material available on SOLID from Bob Martin's(Uncle Bob) site, along with some "effective" examples thrown in from Effective Java Book. Matt was engaging throughout the almost 2 hour session, and I personally got a good deal of information. Just to summarize:

S - Single Responsibility Principle - An Object should have only one reason to change.
O - Open/Closed Principle - A software entity(module, library, routine) should be closed to any modification but be open to extension
L - Liskov Substitution Principle - Derived classes should be substitutable for the base classes
I - Interface Segregation Principle - Having more fine grained interfaces over fat interfaces
D - Dependency Inversion Principle - Depending on abstractions, not concrete implementations.

Wednesday, January 25, 2012

NoSQL at IndyJug

I attended a session on NoSQL databases at IndyJUG today. Tom Hunter, the presenter, had done a very extensive research last year on the entire NoSQL landscape for his personal project, and the presentation was a aggregation of this information - he managed to give a good overview of the different NoSQL databases and had a very interesting way of classifying them, if I remember correctly:
1. Column type databases - Hadoop, Big Table
2. Key/Value type - Memcache,..
3. Document type - MongoDB, Couch DB
4. Graph type - Neo4J

Thursday, September 29, 2011

Indianapolis Java User Group - Presentation on Clojure

I attended a session on Clojure at Indianapolis JUG yesterday. The session was conducted by Carin Meier.

I have wanted to look at Clojure for sometime now, but have been put off by the different looking LISP syntax. Instead I have been learning Scala as the functional JVM based language this year

The session was great, it was about the basics of Clojure but presented in a fun way - it has provided me sufficient amount of motivation to have a second look at Clojure.

The presentation slides are available at Carin Meier's Github account.


Thursday, May 26, 2011

Drools session at Indianapolis Java User Group

I attended a JBoss Drools session at the Indianapolis JUG yesterday evening. The session was presented by Ray Ploski, a Principal Solution Architect with Redhat.
Ray went over the breadth of product offerings within the Drools Umbrella -

  • Drools Expert(the Rule engine)
  • Drools Guvnor(Rules Hosting/Management)
  • Drools Fusion(Complex Event Processing) 
  • Drools Planner(Planning)
  • Drools Flow(Process Flow)
All these product offerings is together referred to as the "Drools Business Logic Integration Platform". 
I had gone into the meeting with the mistaken assumption that Drools is just a rule engine and came out  a little wiser. 

Some notes that I have from the meeting are the following:
  • Ray has hosted the presentation, samples at this location - http://bit.ly/cjug-drools-2011
  • Drools Flow is being merged into jBPM5 - with support for Graphical process flows tightly integrated with Drools Expert.
  • Rules and other artifacts can be versioned within Guvnor - internally it uses JCR as the API for versioning with Jack Rabbit as the implementation
  • Java code can implement a pull based model, to pull in rules from Guvnor - at a specified schedule pull in the latest rules from Guvnor, thus reflecting the rule changes without needing to restart application
  • Drools Expert uses a MVEL dialect to express the condition(LHS) part of the rule
  • One of the largest Drools users has Million and a half rules defined!
PS: E-gineering hosted this meeting at their great new office location.