Logo

Who is talking?

Archive

Migrating to Jekyll

almost 3 years ago | Aishwarya Singhal: Aishwarya Singhal

So finally, I bit the bullet. I have been thinking of migrating my blog to Jekyll for almost 2 years now, never had a true reason. Well now I do, I am free and bored of the themes that Wordpress offers for free. I have been a long time fan of Wordpress, which I believe is still awesome, but I needed more control on how my blog looks and so I moved. Migrating itself was not super hard. There is sufficient help available online, but a quick summary: Get started with [https://help.github.com/articles/using-jekyll-with-pages/] Skip the hello world goodie, create a site instead bundle exec jekyll new bundle exec jekyll build bundle exec jekyll serve Migrate your blogs using ExitWp Migrate comments using Disqus. Read this blog. Use the domain migration tool on Disqus to change the links in the imported comments and get the links right. I basically just did a find and replace in Wordpress exported XML. Modify the SCSS to make your blog look the way you want. Attach Google Analytics to your pages if you like stats. Get yourself a coffee :-) There are three additional benefits of this: The best thing about a Jekyll backed blog is that there is no database involved. It is static content and is super fast in rendering! It is hosted for free on github. And you get to write your blogs in markdown!

Building a web app with node js

over 4 years ago | Aishwarya Singhal: Aishwarya Singhal

NodeJS is an event driven javascript framework that makes writing asynchronous code a piece of cake! For small apps and a limited user base, this is almost magical - the code can be churned out fast, it is clean and it is perfectly unit testable. The purpose of this blog is not to sell node js though, we'll instead look at how an application could be built easily. The applications I work on are primarily client-server, like web apps, or mobile apps with a backend. So here's what my toolkit with node js looks like: Express JS: Sinatra like web framework that gives basic structure to the web app Sequelize JS: ORM framework Require JS: for modularization Node DB Migrate module: just like rails db migrations Mocha JS: For unit tests Chai JS: For test assertions Crypto: For encryptions Angular JS: For the front end MySQL: database Lets keep the front end out of scope for this article and only focus on getting an app that can serve JSON over REST. Setting up the environment Install nodejs Next, we need expressjs Run the following npm install -g express # create the app now. we'll call it 'myapp' express myapp cd myapp node app.js You should now see something like this "Express server listening on port 3000" Yay! You now have a basic Express JS app running! Configuring the app The ExpressJS guide is a pretty good resource for getting started, so I would recommend that you read through it. Next, add the following in package.json under dependencies: "mysql": "*", "supervisor": "*", "db-migrate": "*", "sequelize": "*", "requireindex": "*", "mocha": "*", "crypto": "*", "chai": "*" Save package.json and run "npm install" Supervisor module is a great module for development environments and it auto reloads the app on change, so you dont have to restart your node server every time. To run the app using supervisor, just use "supervisor app.js" Requireindex is a nice module that helps get all objects from  a directory into a single object, without adding a "require" for each file Add the error handler in app.js (as described in expressjs guide) app.use(function(err, req, res, next){ console.error(err.stack); res.send(500, 'Something broke!'); }); Run the app again and access using http://localhost:3000. Adding database support Install mysql We already have the node module included in package.json (mysql), so the app is now ready to start talking to the database We'll use node db migrate module to set up the database. Create a file database.json under myapp. The contents should look as follows: { "dev": { "driver": "mysql", "user": "root", "database": "myapp" }, "test": { "driver": "mysql", "user": "root", "database": "myapp_test" }, "production": { "driver": "mysql", "user": "root", "database": "myapp" } } Create a db.js in the myapp directory with the following contents: var express = require('express'), Sequelize = require("sequelize"); var app = express(); var env = app.get('env') == 'development' ? 'dev' : app.get('env'); // db config var fs = require('fs'); var dbConfigFile = __dirname + '/database.json'; var data = fs.readFileSync(dbConfigFile, 'utf8'); var dbConfig = JSON.parse(data)[env]; var password = dbConfig.password ? dbConfig.password : null; var sequelize = new Sequelize(dbConfig.database, dbConfig.user, password, { logging: true }); exports.sequelize = sequelize The above uses the same file (database.json) as used by db-migrate module so all your configuration stays at one place. It also initializes our ORM framework viz. sequelizejs. To use this, just add require('db.js') as required and get sequelize. Configure unit tests Modify your package.json and add the following under "scripts": "pretest": "db-migrate up -m ./migrations --config ./database.json -e test", "test": "NODE_ENV=test mocha test test/*/**" The above will ensure that your db migrations are run automatically when you run the tests, and also that you don't have to remember longish commands for recursively running tests in sub directories. Add a basic test case under "test" directory. var expect = require('chai').expect, should = require('chai').should(); var db = require("../db.js").sequelize; var DataTypes = require("sequelize"); var assert = require("assert") describe('DB', function(){ it('should check db connection', function(done){ db .query("select count(1) from users") .success(function(o){ expect(o.length).to.not.equal(0); done(); }).error(function(error) { done(); }); }) }) Prepare for test data - create a file _setup.js under tests and put the following: var db = require('../db.js').sequelize; var testData = [ "INSERT INTO users (name) VALUES ('test user');", "INSERT INTO users (name) VALUES ('test user 2');" ]; // now run the test data testData.forEach(function(sql){ db.query(sql).success(function(){ }).error(function(e){ console.log(e); }); }); console.log(">>>> starting tests..."); The SQLs above are obviously just indicative and you'll have to add your SQLs as needed. Run npm test to execute the tests! Build a model Start creating your db migrations (like db-migrate create users) ! They will be stored under myapp/migrations directory. Run the following: db-migrate create users Now open the migration that has been created under migrations directory and add table definition, e.g. var dbm = require('db-migrate'); var type = dbm.dataType; exports.up = function(db, callback) { db.createTable('users', { id: { type: 'int', primaryKey: true, autoIncrement: true }, name: 'string' }, callback); }; exports.down = function(db, callback) { db.dropTable('users', callback); }; Run the migrations to create users table. Now create a directory called "models" under myapp. This is where we'll put our models. Under models, create users.js with the following contents (or similar) var db = require("../db.js").sequelize; var crypto = require('crypto'); var DataTypes = require("sequelize"); var User = function(name, username, password) { this.name = name, this.user_name = username, this.password = password }; var users_table = db.define('users', { name: DataTypes.STRING, user_name: DataTypes.STRING, password: DataTypes.STRING }, { timestamps: false, underscored: true }); User.prototype.save=function(onSuccess, onError) { var shasum = crypto.createHash('sha1'); shasum.update(this.password); this.password = shasum.digest('hex'); users_table.build(this).save().success(onSuccess).error(onError); }; User.find=function(username, password, onSuccess, onError) { users_table.find({ where: {user_name: username, password: password}, attributes: ['id', 'name', 'user_name'] }).success(onSuccess).error(onError); }; User.lookup=function(name, onSuccess, onError) { users_table.findAll( { where : [ "name like ?", '%' + name + '%' ] } ).success(onSuccess).error(onError); }; exports.get=User; exports.table=users_table; As a reminder, we use sequelizejs for ORM and crypto for encryptions above. To use this model, all we now need is to create an object of User and call user.save(), or directly call User.find or User.lookup as needed. Notice that these take callbacks for success and error, thats because node js is a totally event driven framework and everything is synchronous. These methods don't return anything :smile: Lets add a route, create user.js under routes directory. var User = require('../models/users').get; exports.authenticate = function(req, res) { User.find(req.body.username, req.body.password, function(o) { if (o) { res.json(o.selectedValues); } else { res.send(401, "Auth failed"); } }, function(error) { console.log(error); res.send("Auth failed"); }); }; And in app.js, add the route app.post('/authenticate', user.authenticate); All done! You now have an app that can connect to the database and authenticate users! In the next blog, we'll see how we can quickly assemble a front end

Building a web app with node js

over 4 years ago | Aishwarya Singhal: Aishwarya Singhal

NodeJS is an event driven javascript framework that makes writing asynchronous code a piece of cake! For small apps and a limited user base, this is almost magical – the code can be churned out fast, it is clean and … Continue reading →

Don’t write off Microsoft just yet!

almost 5 years ago | Aishwarya Singhal: Aishwarya Singhal

I just bought a new laptop with the cool new Windows 8 installed. I must admit that I was a bit skeptical of how the new OS would be, but its totally taken me by surprise, and in a good … Continue reading →

Don't write off Microsoft just yet!

almost 5 years ago | Aishwarya Singhal: Aishwarya Singhal

I just bought a new laptop with the cool new Windows 8 installed. I must admit that I was a bit skeptical of how the new OS would be, but its totally taken me by surprise, and in a good way!  First, I absolutely adore the new Metro layout. Its like a cool dashboard where I have all my tools and information handy for me to get started. From facebook to gmail to google search, everything is a shortcut on there. And its not just a shortcut! The mails tile shows new ones and facebook one shows the highlights - everything that makes you decide if you want to click that icon or not. Similarly, there are news feeds, weather updates and other handy info. Its really much more useful than the mostly empty windows desktop that exists on previous versions. And its much brighter and colorful too! Secondly, IE 10 is a total pleasure to use. Its super fast, and feels much lighter. I also hear that it finally adheres to global standards too (yay, developers rejoice) ! Thirdly, each new window/ app is a full screen by default. No task bar, no title bar, nothing. It makes the full use of the screen - can it get better ?! Oh well, some things require 2 clicks (including a right click) that should really just need one. Like closing windows. Yeah. You either drag a window to the bottom to ask it to go to hell (or where ever), or you right click, find yourself a cross button and close the damn thing. I wish there was a close button that would appear when I hover around one of the corners, closing a window should be a one click thing. And I could not install Google Chrome on Win 8 - its just kept on hanging up on me. I think the performance of the OS and system in general is pretty good, and the fact that the same system will run on mobile and desktop/ laptop computers is pretty encouraging. May be we should consider how we'll develop apps for windows along with Android and iOS ? ha ha! I hear Windows 8 is all HTML and JS anyways!

Line Charts with d3 js

almost 5 years ago | Aishwarya Singhal: Aishwarya Singhal

Want to do a line chart with d3? There are no ready APIs right? At least none that I could find. What I did find was http://benjchristensen.com/2012/05/02/line-graphs-using-d3-js/ (very useful!) and I hacked up a line chart taking cue from there. … Continue reading →

Line Charts with d3 js

almost 5 years ago | Aishwarya Singhal: Aishwarya Singhal

Want to do a line chart with d3? There are no ready APIs right? At least none that I could find. What I did find was http://benjchristensen.com/2012/05/02/line-graphs-using-d3-js/ (very useful!) and I hacked up a line chart taking cue from there. Here's an example: And the code? <!DOCTYPE html> <html lang="en"> <head> <title>Line Charts</title> <script src="http://code.jquery.com/jquery-1.8.2.min.js"></script> <script src="http://d3js.org/d3.v2.js"></script> <script type="text/javascript"> function getDate(d) { var dt = new Date(d.date); dt.setHours(0); dt.setMinutes(0); dt.setSeconds(0); dt.setMilliseconds(0); return dt; } function showData(obj, d) { var coord = d3.mouse(obj); var infobox = d3.select(".infobox"); // now we just position the infobox roughly where our mouse is infobox.style("left", (coord[0] + 100) + "px" ); infobox.style("top", (coord[1] - 175) + "px"); $(".infobox").html(d); $(".infobox").show(); } function hideData() { $(".infobox").hide(); } var drawChart = function(data) { // define dimensions of graph var m = [20, 40, 20, 100]; // margins var w = 700 - m[1] - m[3]; // width var h = 360 - m[0] - m[2]; // height data.sort(function(a, b) { var d1 = getDate(a); var d2 = getDate(b); if (d1 == d2) return 0; if (d1 > d2) return 1; return -1; }); // get max and min dates - this assumes data is sorted var minDate = getDate(data[0]), maxDate = getDate(data[data.length-1]); var x = d3.time.scale().domain([minDate, maxDate]).range([0, w]); // X scale will fit all values from data[] within pixels 0-w //var x = d3.scale.linear().domain([0, data.length]).range([0, w]); // Y scale will fit values from 0-10 within pixels h-0 (Note the inverted domain for the y-scale: bigger is up!) var y = d3.scale.linear().domain([0, d3.max(data, function(d) { return d.trendingValue; } )]).range([h, 0]); // create a line function that can convert data[] into x and y points var line = d3.svg.line() // assign the X function to plot our line as we wish .x(function(d, i) { // return the X coordinate where we want to plot this datapoint return x(getDate(d)); //x(i); }) .y(function(d) { // return the Y coordinate where we want to plot this datapoint return y(d.trendingValue); }); function xx(e) { return x(getDate(e)); }; function yy(e) { return y(e.trendingValue); }; $("#chart").append("<p><small><em>Please move the mouse over data points to see details.</em></small></p>"); // Add an SVG element with the desired dimensions and margin. var graph = d3.select("#chart").append("svg:svg") .attr("width", w + m[1] + m[3]) .attr("height", h + m[0] + m[2]) .append("svg:g") .attr("transform", "translate(" + m[3] + "," + m[0] + ")"); // create yAxis var xAxis = d3.svg.axis().scale(x).ticks(d3.time.months, 1).tickSize(-h).tickSubdivide(true); // Add the x-axis. graph.append("svg:g") .attr("class", "x axis") .attr("transform", "translate(0," + h + ")") .call(xAxis); // create left yAxis var yAxisLeft = d3.svg.axis().scale(y).ticks(10).orient("left"); //.tickFormat(formalLabel); // Add the y-axis to the left graph.append("svg:g") .attr("class", "y axis") .attr("transform", "translate(-25,0)") .call(yAxisLeft); // Add the line by appending an svg:path element with the data line we created above // do this AFTER the axes above so that the line is above the tick-lines graph .selectAll("circle") .data(data) .enter().append("circle") .attr("fill", "steelblue") .attr("r", 5) .attr("cx", xx) .attr("cy", yy) .on("mouseover", function(d) { showData(this, d.trendingValue);}) .on("mouseout", function(){ hideData();}); graph.append("svg:path").attr("d", line(data)); graph.append("svg:text") .attr("x", -200) .attr("y", -90) .attr("dy", ".1em") .attr("transform", "rotate(-90)") .text("Trending Value"); $("#chart").append("<div class='infobox' style='display:none;'>Test</div>"); } var draw = function() { var data = [ {'date': "2012-10-01", 'trendingValue': 1000}, {'date': "2012-09-01", 'trendingValue': 900}, {'date': "2012-08-01", 'trendingValue': 1100}, {'date': "2012-07-01", 'trendingValue': 950}, {'date': "2012-06-01", 'trendingValue': 1050}]; drawChart(data); } </script> <style> #chart path { stroke: steelblue; stroke-width: 2; fill: none; } .axis { shape-rendering: crispEdges; } .x.axis line { stroke: lightgrey; } .x.axis .minor { stroke-opacity: .5; } .x.axis path { display: none; } .y.axis line, .y.axis path { fill: none; stroke: #000; } .infobox { border:2px solid steelblue; border-radius:4px; box-shadow:#333333 0px 0px 10px; margin:200px auto; padding:5px 10px; background:rgba(255, 255, 255, 0.8); position:absolute; top:0px; left:0px; z-index:10500; font-weight:bold; } </style> </head> <body onload="draw();"> <div id="chart"> </div> </body> </html>

Why Clojure scares me

over 5 years ago | Aishwarya Singhal: Aishwarya Singhal

There has been a lot of buzz about this relatively new language. Its a new kid on the block, it is Lisp, functional and runs on the JVM. Nice! But its very fact that its a Lisp scares me off. … Continue reading →

Why Clojure scares me

over 5 years ago | Aishwarya Singhal: Aishwarya Singhal

There has been a lot of buzz about this relatively new language. Its a new kid on the block, it is Lisp, functional and runs on the JVM. Nice! But its very fact that its a Lisp scares me off. When I look at Clojure code, compact as it may be, I just see a lot of brackets. And I mean a lot of them. I was reading a deck yesterday that admitted that long time Java developers may suffer from this 'problem', and I do fall in that category :-) Even if I ignore all those scary brackets, the way the code is written, it looks like prefix notation (it reminds me of Yoda in Star Wars who talked in a very funny and interesting manner, but I won't use that dialect in practice). I mean seriously, when I first learned about numbers and Algebra, I wrote expressions as 1 + 2, and not + 1 2. The latter is not really a natural way for me. Oh yes, I can get used to the latter too, but I think for a long time, I would just be doing a translation for myself in my head. And it would surely be slow and painful. I must admit that this is just a feeling - I have only _seen _Clojure yet, not practiced it. And there are many things that are good in this language. For me, Scala works wonders and I intend to stick to it for now.

New Features on Factile

over 5 years ago | Aishwarya Singhal: Aishwarya Singhal

Factile, as you know, is a free and open source survey platform. It generated significant interest in the first few days of its launch and I received some feedback that I thought would be good to build into the tool. I have just released a new version at http://www.factile.net and the following are the main changes: Better Navigation: Clickable bars showing the steps in survey creation/ editing to enhance user experience. Offline Survey Capability: Even if the survey participants are in transit or are in areas of unreliable connectivity, they can still 'work offline'. i.e. They can keep on working through the survey and just submit the results once they are back on the network! Easy-peasy ! Word Clouds: Factile now has the capability to build a word cloud (aka tag cloud) of free text responses. Factile combines all responses for free text questions, removes common words (aka stop words) and generates a word cloud. Just so you can analyse survey takers' comments much more easily. Insights: This is a feature that was always planned and was delayed. You can now select a group of questions and define constraints to generate a list of top 5 combinations as picked by the users. So for example, if you wanted to see what demographic group tweets/ blogs the most, you could comine the demographics related questions, add a constraint around tweeting/ blogging and get sorted and aggregated insights. Custom URI: Would you like your survey to be called http://www.factile.net/mycoolsurvey instead of the long system generated identifier? You can do so now! Obviously, Factile is freely downloadable and customizable (and these surveys work on mobile devices, as would be convenient to use on a mobile device and not as small difficult to click HTML radio buttons). You can let me know if you want a feature/ faced a bug by logging an issue on github, or just leave a comment on this blog! You can also send an email at https://groups.google.com/group/factile. I did a quick video on the use of Factile a week or so back and uploaded to YouTube. You can watch it here.

New Features on Factile

over 5 years ago | Aishwarya Singhal: Aishwarya Singhal

Factile, as you know, is a free and open source survey platform. It generated significant interest in the first few days of its launch and I received some feedback that I thought would be good to build into the tool. … Continue reading →

Factile – A free online survey tool

over 5 years ago | Aishwarya Singhal: Aishwarya Singhal

On Friday last week, I launched Factile at http://www.factile.net. It is a free and open source survey platform that I created and aims at making the job of data collection and analysis simpler. It supports a variety of question types … Continue reading →

Factile - A free online survey tool

over 5 years ago | Aishwarya Singhal: Aishwarya Singhal

On Friday last week, I launched Factile at http://www.factile.net. It is a free and open source survey platform that I created and aims at making the job of data collection and analysis simpler. It supports a** variety of question types** (Text boxes, Radio buttons, Check boxes, Combo boxes (dropdowns), Text areas, Plain texts, matrix of choices/ rating scales). The surveys generated are fully mobile device compatible. So you can create a survey and share it with people to take on iPads/ iPhones/ BackBerry/ Samsung S2s, really, anywhere! It is truly free and unlimited. There is zero usage cost, and you can add as much content to your survey as you like. And, if you wanted to download it and install on your infrastructure, you can! Whats more? You can define logic in the survey, you can build charts of the captured data, customize the appearance of the survey to match your requirements and the best is, you can request for missing features and I'll be happy to oblige! Check out http://www.factile.net and let me know of what you think.

Deploy Play 2 application on AWS with Tomcat and Apache HTTPD

over 5 years ago | Aishwarya Singhal: Aishwarya Singhal

I have created a web application on Play 2.0 framework, in Scala. To deploy it, I looked at various cloud options – Amazon looks the best because, well its free :-)  Once the instance was created, it already had Java … Continue reading →

Deploy Play 2 application on AWS with Tomcat and Apache HTTPD

over 5 years ago | Aishwarya Singhal: Aishwarya Singhal

I have created a web application on Play 2.0 framework, in Scala. To deploy it, I looked at various cloud options - Amazon looks the best because, well its free :-)  Once the instance was created, it already had Java 6, I installed Apache HTTPD and Tomcat 7. Lets first add some swap space sudo -i dd if=/dev/zero of=/swapfile bs=1024 count=524288 mkswap /swapfile swapon /swapfile Now edit /etc/fstab and append the following line to it: /swapfile swap swap defaults 0 0 Ok, lets install tomcat and httpd now. yum -y install httpd mkdir -p /var/www/html/assets mkdir -p /usr/share/tomcat7 cd /usr/share/tomcat7 wget http://apache.mirrors.timporter.net/tomcat/tomcat-7/v7.0.27/bin/apache-tomcat-7.0.27.tar.gz gzip -d apache-tomcat-7.0.27.tar.gz tar xvf apache-tomcat-7.0.27.tar mkdir -p /var/log/tomcat7 /var/cache/tomcat7/temp /var/lib/tomcat7/webapps /var/cache/tomcat7/work rm -rf logs temp webapps work ln -s logs /var/log/tomcat7 ln -s webapps /var/lib/tomcat7/webapps ln -s work /var/cache/tomcat7/work ln -s temp /var/cache/tomcat7/temp useradd -d /usr/share/tomcat7 tomcatusr chown -R tomcatusr /var/log/tomcat7 chown -R tomcatusr /var/cache/tomcat7/ chown -R tomcatusr /var/lib/tomcat7 chown -R tomcatusr /usr/share/tomcat7 Now open the server.xml (inside /usr/share/tomcat7/conf) and comment out the connector for port 8080 <!-- Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" / --> Look for 8009 (AJP connector) and modify it to: <Connector port="8009" enableLookups="false" redirectPort="8443" protocol="AJP/1.3" URIEncoding="UTF-8" /> Now create a start up script under /etc/init.d and call it tomcat7: #!/bin/bash # Tomcat7: Start/Stop Tomcat 7 # # chkconfig: - 90 10 # description: Tomcat is a Java application Server. . /etc/init.d/functions . /etc/sysconfig/network CATALINA_HOME=/usr/share/tomcat7 TOMCAT_USER=tomcatusr LOCKFILE=/var/lock/subsys/tomcat RETVAL=0 start(){ echo "Starting Tomcat7: " su - $TOMCAT_USER -c "$CATALINA_HOME/bin/startup.sh" RETVAL=$? echo [ $RETVAL -eq 0 ] && touch $LOCKFILE return $RETVAL } stop(){ echo "Shutting down Tomcat7: " $CATALINA_HOME/bin/shutdown.sh RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f $LOCKFILE return $RETVAL } case "$1" in start) start ;; stop) stop ;; restart) stop start ;; status) status tomcat ;; *) echo $"Usage: $0 {start|stop|restart|status}" exit 1 ;; esac exit $? All set. Now let us connect the HTTPD to talk to Tomcat. Open /etc/httpd/conf/httpd.conf for editting Go to the end of the file and uncomment the VirtualHost (port 80). The whole block, of course. Add the following inside the VirtualHost ErrorLog logs/error_log CustomLog logs/ajp.log combined SetOutputFilter DEFLATE BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html # Don't compress images SetEnvIfNoCase Request_URI \ \.(?:gif|jpe?g|png)$ no-gzip dont-vary # Make sure proxies don't deliver the wrong content #Header append Vary User-Agent env=!dont-vary ExpiresByType image/gif A604800 ExpiresByType image/png A604800 ExpiresByType image/jpg A604800 <Proxy *> AddDefaultCharset Off Order deny,allow Allow from all </Proxy> ProxyPass /assets ! ProxyPass / ajp://localhost:8009/ ProxyPassReverse / ajp://localhost:8009/ The above will enable gzip compression on your pages (for performance), cache images on the client for a week and enable you to serve static assets from the webserver itself. Set docroot and error pages: DocumentRoot "/var/www/html" ErrorDocument 404 /assets/html/missing.html ErrorDocument 503 /assets/html/missing.html All done. Now use the Play WAR plugin to generate the WAR file. Copy the generated WAR file into /var/lib/tomcat7/webapps as ROOT.war (otherwise you don't get the "/" root URL). Package the static files from inside APP_HOME/public separately into a TAR and extract into the /var/www/html/assets directory.

Generating Excel in Play 2

over 5 years ago | Aishwarya Singhal: Aishwarya Singhal

Play 1.x has a nice module that allows you to create Excel sheets. The new Play 2.x however lacks this capability. Or atleast is not very evident. While I found most of the information by searching the net, I thought it may help someone to just have quick start notes here. I use Apache POI to generate Excel. I also wanted to create .xlsx rather than a plain .xls. Add the following to your Build.scala (under APP_HOME/project) val apache_poi = "org.apache.poi" % "poi" % "3.8" val apache_poi_ooxml = "org.apache.poi" % "poi-ooxml" % "3.8" val appDependencies = Seq( ... apache_poi, apache_poi_ooxml ) Actually, you don't need ooxml if you only want to create a plain xls (and not a xlsx). Now start the Play console ('play') and execute 'run'. This will resolve the dependencies and get you the requisite libraries. Now generate a excel: import java.io.File import java.io.FileOutputStream import org.apache.poi.xssf.usermodel._ val file = new File("mydata.xlsx") val fileOut = new FileOutputStream(file); val wb = new XSSFWorkbook val sheet = wb.createSheet("Sheet1") var rNum = 0 var row = sheet.createRow(rNum) var cNum = 0 val cell = row.createCell(cNum) cell.setCellValue("My Cell Value") wb.write(fileOut); fileOut.close();  All done! Now, in your controller action, add the following: Ok.sendFile(content = file, fileName = _ => "mydata.xlsx")

Generating Excel in Play 2

over 5 years ago | Aishwarya Singhal: Aishwarya Singhal

Play 1.x has a nice module that allows you to create Excel sheets. The new Play 2.x however lacks this capability. Or atleast is not very evident. While I found most of the information by searching the net, I thought … Continue reading →

What happened to Slate?

over 5 years ago | Aishwarya Singhal: Aishwarya Singhal

Slate is still very alive (and kicking), I just have been busy with my day to day job to make aggressive improvements lately. Plus, I did need to urgently catch up with Play 2.0 and Mongo DB so whatever free time I get these days, goes there. I intend to get fully active on Slate again by early June, though. In the meanwhile, Eclipse based Scala IDE seems to have improved massively. It is much faster, smarter and does not hang up that often. I now prefer using text editors for writing Scala and Ruby though, so I am very excited about making Slate a light and usable development environment. Early releases of Slate had a number of problems, especially in the UI. I believe most of them are now fixed, but there's still a lot I would like to do with it.

What happened to Slate?

over 5 years ago | Aishwarya Singhal: Aishwarya Singhal

Slate is still very alive (and kicking), I just have been busy with my day to day job to make aggressive improvements lately. Plus, I did need to urgently catch up with Play 2.0 and Mongo DB so whatever free … Continue reading →

An IDE for Scala

about 6 years ago | Aishwarya Singhal: Aishwarya Singhal

I have been working on Scala in my spare time for the past ~3 months now and I absolutely love it! It is extremely powerful, the syntax is sleek and it has an API for almost every basic operation! My choice … Continue reading →

Lets Play with Scala

about 6 years ago | Aishwarya Singhal: Aishwarya Singhal

Sometime earlier this year, I read a blog  and an article. These are interesting thoughts and coming from the Java space of enterprise applications, I know exactly how bad performance and unmaintainable the code can get. Scala’s claim of reducing the code by a factor of 2 or 3 is extremely tempting! Add to that a lot [...]