Friday, December 20, 2013

Changing my webapps development workflow

A few months ago, I though I was running a pretty good setup for doing web application development. It was built around Netbeans, auto-compiles (for Less, Sass or Coffeescript) and CDNs. I did chug out a lot of code and with a "run test" code bind, it worked out pretty good. This was until I started to get tired of tracking my JavaScript dependencies and that my Internet was acting iffy (F*** Y** PLDT).

Enter Yeoman. Yeoman is described as a bunch of tools that "improve your productivity and satisfaction" as web developer. I'd buy that. Nothing is more satisfying that looking at the text output of a console with a success message at the end.

Getting started with Yeoman is surprising easy since at minimum you only need Node.js. Node.js has an automated installer for Windows which makes is near stupid-proof. The Linux people, I don't have to worry. The details can be found at Yeoman's website.

To succeed with Yeoman, you need to understand the 3 core tools:
  1. yo - tool to create (or scaffold) your app. If you're like me that tries out a lot of "flavor of the month" JS libs and whatnot, you'll like yo, a lot.
  2. bower - script/lib gopher or dependency manager. That cool library needing "other" libraries? bower will get those and that cool library. 
  3. grunt - is used to build, preview and test your project. You don't really have to config it since yo will already config grunt for your project. You just basically need to write the test. 
As for your workflow with Yeoman, it's quite simple:
  1. Make folder -> go to folder
  2. yo webapp
  3. bower install library_name -> for example: bower install angular to install the latest angularJS
  4. Repeat #3 until you have everything you need.
  5. grunt server -> runs web server to preview your app
  6. Write code, write, test fresh browser -> you don't have to stop, start the server to see changes
  7. Repeat #6 unless you want to run test
    • grunt test -> test runner
    • Go to #5 if the tests fails or you want to tweak something
    • Go to #8 if everything is A OK
  8. grunt -> deployment
I'm using Netbeans with this workflow.

Merry Christmas everyone and happy coding.

Sunday, November 24, 2013

Winamp, a threat, a petition, AngularJS and shit is about to get real

A few days ago, I made a threat that I will remove people from the CDO-ITG group page if they didn't sign a certain petition. I said that I was doing to remove every shit on this group who didn't sign the Winamp petition and I said that I will know who didn't sign. Everyone laughed. Not. fucking. anymore.

Change.org has an API that allows me get at all of the signatures in the Winamp petition. Although, Change.org's API isn't quite mature, it's usable and quite easy to use with AngularJS. Here is a snippet:

wapp.factory('changeOrgService', function($resource){

    var _changeOrg = {};
    
    _changeOrg.getSignatures = function(petitionId){
        var baseUrl = 'https://api.change.org/v1/petitions';
        return $resource(baseUrl + '/:id/signatures?api_key=' + winampPapp.api_key + "&callback=JSON_CALLBACK",{id: petitionId}, 
            { get: { method: 'JSONP', params: { page: 1} }});
    };

    _changeOrg.getPetitionId = function(url){
        var baseUrl = 'http://api.change.org/v1/petitions/get_id';
        return $resource(baseUrl, {},
            { get: {method: 'JSONP'}, params:{api_key: winampPapp.api_key, petition_url: url, callback: 'JSON_CALLBACK'}});
    };

    return _changeOrg;
});

That should be easy to figure since its only a pretty simple AngularJS factory that depends on the ngResource module to get at the data. Add underscore and then you can do something interesting with the petition signature data like figure out how many signed from the Philippines (26), how many are from the Cagayan de Oro (DO YOU WANT TO FUCKING KNOW?! DO YOU?).


Now, how about REALLY signing that petition before I really do something crazy like find out where you live.

Friday, November 22, 2013

Why use Fiddles to teaching programming

  1. No more IDEs to figure out or decide on (every CS instructor and developer has an opinion on IDEs. Great flamewars have started this way.) 
  2. No more complex workflows like requiring source file names must follow a certain pattern, save into a specific folder, etc.
  3. No more projects submitted via a USB drive; If you're still doing this as a CS instructor now, change careers because you suck
  4. No more SDK installations or copying binaries for specific programming languages
  5. No more fighting a version control system; Let's face it teaching programming to freshmen or sophomores is hard enough and you still want to muddy the waters with a VCS?
  6. (some) Fiddles are collaborative; 2 or more students working on the same source file which makes for some interesting group project options.
  7. Fiddles can be shared via social networking; we already share too much of our personal life online why not your code?
  8. Fiddles are bookmark-able so they can be submitted as is and you can quickly see if it can run or not
  9. Fiddles are available for every language (some examples)
  10. And yes all of them are free
Fiddles should change the way how we teaching programming to all levels, if you disagree, tell me I'm interested in hearing what argument you come up with.

Friday, November 15, 2013

When we need something more than Firebug

Us web developers in our quest to build something unique will eventually come upon a wall that looks insurmountable with our current set of debugging tools like Firebug and Chrome's or IE's developer tools. Sometimes you just need something that can work at the HTTP protocol. This is where Fiddler2 comes in. Fiddler is a web debugging proxy for any browser, system or platform. Which makes it quite handy if you're doing AJAX stuff on a lot of different platforms from Java to Node.js.

What's really special with Fiddler is the composer feature which allows to make AJAX verb (GET, DELETE, PUT, HEAD, etc.) calls to your server side API. It then allows you to look at the response headers, cookies, the raw results and a bunch of other values to help you debugged that code.

Use this with Mozilla Firefox to get the most mileage out of it since it does integrate into it quite nicely. Chrome doesn't do it because of that new rule that you can't install a plugin that's not found in the Chrome store.

It also has a nice set of add-ons which is just icing on cake. I like StresStimulus add-on which allows you to do load testing with your web apps.

Another thing is this thing is free and will run on Linux boxes (needs Mono though).

Add this to your toolbox.

Tuesday, October 15, 2013

Knockout style computed fields in AngularJS (sort of)

AngularJS has a few peculiar things. Here's a pair of them.

Suppose you have 3 input text fields - f1, f2, f3. And want you want is to have f3 a "computed" field based on what's the values on f1 and f2. Simple enough, right? Not exactly.

If you do did something like this:

<div ng-app>  
   <div ng-controller="CTRL">  
     <input type="text" ng-model="f1" />  
     <input type="text" ng-model="f2" />  
     <input type="text" value="{{total()}}" />  
     <p>{{'Angular works!'}}</p>  
   </div>  
 </div> 

And your Angular script is like this:

function CTRL ($scope) {
    $scope.f1= 3;
    $scope.f2= 4;
    $scope.total = function() {return $scope.f1 + $scope.f2;};
}

You are in for a bad time. You will notice it will work at the start but when you change the value on either f1 or f2, the total field is showing a concatenated string and not a sum. DAFUQ!  Peculiarity #1. The fix is actually pretty easy if you use a directive.

var app = angular.module('intDirective', []);

app.directive('integer', function(){
    return {
        require: 'ngModel',
        link: function(scope, ele, attr, ctrl){
            ctrl.$parsers.unshift(function(viewValue){
                return parseInt(viewValue);
            });
        }
    };
});

To use this is to add a ng-app="intDirective" property to the root div and the input tags should look like this:

<div ng-app='intDirective'>  
   <div ng-controller="CTRL">  
     <input type="text" ng-model="f1" integer/>  
     <input type="text" ng-model="f2" integer/>  
     <input type="text" value="{{total()}}" />  
     <p>{{'Angular works!'}}</p>  
   </div>  
 </div> 

OK, its looking good but try typing in a character on either f1 or f2? Yes, another thing we have do. We have to check the value being typed it is not shit (sometimes called Validation).

var app = angular.module('intDirective', []);
var INTEGER_REGEXP = /^\-?\d*$/;
app.directive('integer', function(){
    return {
        require: 'ngModel',
        link: function(scope, ele, attr, ctrl){
            ctrl.$parsers.unshift(function(viewValue){
                ctrl.$parsers.unshift(function(viewValue) {
                if (INTEGER_REGEXP.test(viewValue)) {
                   // it is valid
                   ctrl.$setValidity('integer', true);
                   return parseInt(viewValue);
                } else {
                   // it is invalid, return undefined (no model update)
                   ctrl.$setValidity('integer', false);
                   return undefined;
                }
            });
        }
    };
});

What's left is a simple $watch function to mimic Knockout computed fields (Peculiarity #2). Just add this snippet inside the controller.

    $scope.$watch(function(){
        return $scope.val1 + $scope.val2;
    }, function(newValue, oldValue){
        $scope.computed = newValue;
    });

There.

Wednesday, October 9, 2013

AngularJS with underpants

What I really meant was AngularJS with underscore but what the heck.

AngularJS as powerful as it is doesn't really have a lot utility methods and this is where underscore comes in. Underscore provides 80-odd functions that support both the usual functional suspects: map, select, invoke — as well as more specialized helpers.

To get the most of underscore with AngularJS, you have to "provide" underscore into AngularJS via a factory method:
var myapp= angular.module('underscore', []);
 myapp.factory('_', function() {
  return window._; // underscore has been loaded before this script
 }); 
With that, we can now inject underscore into our controllers:
myapp.controller("SomeCtrl",[$scope, _, function($scope, _){
    $scope.maxVal = _.max([1,2,3]); // Returns 3
});

Which leads to a couple of pretty handy stuff like checking for undefined values:
myapp.controller("SomeCtrl",[$scope, _, function($scope, _){
    if(_.isUndefined($scope.someValue){
          // do something because someValue is undefined
    }
});
Or do a search over some array using some attribute without resorting to a loop.
myapp.controller("SomeCtrl",[$scope, _, function($scope, _){
    
var data = [{model:"T", manufacturer: "Nokia"},
            {model:"S", manufacturer:"Samsung"},
            {model:"r8", manufacturer:"Cherry Mobile"},
            {model:"One", manufacturer:"HTC"}];
//Code to fetch a Cherry Mobile phone
var phone = _.where(data, {manufacturer: "Cherry Mobile"});
// phone should be [{model:"r8", manufacturer:"Cherry Mobile"}]
});
By combining these awesome frameworks, you're setting up yourself to dish out some serious can of whoop ass.

Sunday, September 29, 2013

Cold Sunday morning code

It's been interesting morning. I woke up way to early on account of the cold. A cup of coffee later, I decided to sign up and try out these free NoSQL backends which could be used for AngularJS apps. This is where I stumbled upon Mongolab.com. Mongolab is a mongodb as a service website and gives out a free 500MB account which is enough when you're trying out their stuff. But trust me when I tell you that unless your pulling 5,000 hits per month on your app that 500MB will last for a long bit.

Since I was on a roll getting free shit on the Internet, I decided to also get a github.com account. You can only ride a joke for so long, right Josan Astrid Dometita?

Amazingly, while I was trying to learn how to use the MongoLab APIs, I also found out that someone has already written an adapter for it for AngularJS.

It didn't take long to get all the stuff together. Twitter-bootstrap for my interface framework, AngularJS as my app framework, Mongolab for my backend. And since the point was to learn how to do stuff, I decided to do a simple contacts app with full CRUD features. It was easy as pie!

Here's the github repo for the code if you want to study it also: https://github.com/killertilapia/Mongolabular

Now with that done, we'll see what other stuff I can do with it. *knowing grin*

Also, I can now tag Google+ friends in my blog! SWEET! +Romar Mayer Micabalo +Paul Michael Labis +Jon Doblados +Arthur Vincent Simon +Lionel Amarado

Sunday, September 8, 2013

Parsing JSON with keys that have the at sign or @ symbol

I had to work with this interesting JSON file which had a metadata section which can be accessed with @metadata key. Here's a small sample of the JSON file:

 "twitter_handle": "..........",
 "website": ".............",
 "@metadata": {
  "Access-Control-Allow-Credentials": "true",
  "Raven-Entity-Name": "4fff7413",
  "@id": "4fff7413-f1bd-4e00-ab51-6754f1111c03",
  "Last-Modified": "2013-09-08T08:29:35.2587326Z",
  "Raven-Last-Modified": "2013-09-08T08:29:35.2587326",
  "@etag": "01000000-0000-0003-0000-000000000001",
  "Non-Authoritative-Information": false
 }

The twitter_handle or the website data are just normal JSON values so they are not that interesting but the @metadata is where it gets interesting. How do you access that?

At first I tried object.@metadata, didn't work. So I tried the next one which is object[@metadata] which also didn't work. I then found out over at StackOverflow that I was quite near. All I had to do was put single quotes so it would look like object['@metadata'].

It also works if you're trying to get a value inside, like say @id within @metadata. It would end up looking like object['@metadata']['@id'].


Sunday, August 18, 2013

Bootstrap tabs and the curious case of the missing bottom border

I'm a big fan of Twitter bootstrap. It's a big help for the design impaired. But as helpful Bootstrap is it still has a few things that you have to do yourself. It is where my story begins. I needed to get to here:

Tabs pulled right with an H4 element on the left WITH a bottom border


From here. This is how it should look like with the default markup using Bootstrap.

Tabs pulled right with an H4 element on the left WITHOUT a bottom border

I will post the markup here. The HTML markup is pretty standard.

     <div class="col-8 subheader">  
       <h4 class="pull-left">Postings</h4>  
       <ul class="nav nav-tabs pull-right" id="myTab">  
         <li><a href="#interesting" data-toggle="tab">Interesting</a></li>  
         <li><a href="#freshest" data-toggle="tab">Freshest</a></li>  
         <li><a href="#popular" data-toggle="tab">Popular</a></li>  
       </ul>   
     </div> 

The interesting part is getting the bottom border to work out. If all goes to plan it should stretch from the "Postings" element up to the first tab. My solution isn't that good if you're into strict semantic HTML5 but I'd rather get it working than worrying about writing proper semantic HTML5. At least it will validate.
     
     <div class="col-8 subheader">  
       <div id="btm-border"></div>
       <h4 class="pull-left">Postings</h4>  
       <ul class="nav nav-tabs pull-right" id="myTab">  
         <li><a href="#interesting" data-toggle="tab">Interesting</a></li>  
         <li><a href="#freshest" data-toggle="tab">Freshest</a></li>  
         <li><a href="#popular" data-toggle="tab">Popular</a></li>  
       </ul>   
     </div> 

The other half is the CSS rule. I write CSS using Less. Why? BECAUSE REASONS!

.subheader{
    position: relative;

    #btm-border{
        border-bottom: 1px solid #ddd;
        position: absolute;
        width: 446px;
        top: 42px;
    }
}

Friday, August 2, 2013

WTF Win8! No adhoc networking? No wonder it sucks.

This is more rant than developer talk.

A few nights ago, my laptop's hard disk was failing and I had to replace it and while I was at it I decided to update to Windows 8. I thought why the hell not? I did have a valid key and who know I might like it. I WAS SOOO FUCKING WRONG!!

The install process was painless, then there's a lot of eye candy and then it started to go downhill from there. First is that ribbon, strip on the right side, what is that all about? And why doesn't have to pop out ONLY WHEN I put my mouse pointer to the TOP RIGHT corner of the screen? And if I can customize it, WHERE THE FUCK is the customization screen so I can change it's behavior.

Second, WHY THE FUCK NO wireless adhoc connections? Yes, I found the couple of blogs telling how it can be done but involves opening the command line and THAT IS BULLSHIT! And if you make the argument of using third-party software like Connectify, FUCK YOU!

There's a third one, fourth one, fifth one but I don't want to talk about BECAUSE REASONS!

The only bright spot for me is that my laptop boots up and shuts down faster and my Visual Studio runs better. Almost everything else was a disaster.


Monday, July 29, 2013

Overcoming the same-origin policy in AJAX/JS programming

If you are serious with AJAX (and/or JavaScript) then you probably ran into the same-origin policy. The policy is an important security concept and SHOULD NOT be turned off. But like everything else on the web, it cramps programming or limits system designs and overcoming it is a mess of kludges and dirty hacks. Enter CORS.

Cross-Origin Resource Sharing (CORS) is a specification that allows you to implement cross-domain request (ie. use an AJAX resource from another domain). The spec defines a set of headers that allow the browser and server to communicate about which request are (and are not) allowed. It isn't that hard and its supported by all browsers (it even works on IE8, which is down-right surprising).

For example, Adding CORS on an Apache server is just:

headtroll@trollmachine:/# a2enmod headers

And then to expose the header, you simply add the following to your Apache .conf file:

Header set Access-Control-Allow-Origin "*"

More details here.

As for the client side, HTML5Rocks.com already has a tutorial on how to use CORS.

Saturday, July 20, 2013

DAT Angular

This is part 5 of my Resteasy Tapestry with AngularJS tutorial. This is last part of the tutorial where you combine both. You should end up with a Resteasy-Tapestry5 server with the Ajax APIs and a second web application that uses the APIs via AngularJS. 

Using Ajax APIs with AngularJS is easy if you use Angular-Resource. Angular-Resource is not a default add-on for AngularJS. You don't have to download it since Google's CDNs also serve it.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>  
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular-resource.js"></script>  
<script type="text/javascript" src="js/tangled.js"></script>  

The tangled.js script there is where we write the interesting parts. Here's a partial of that script:

angular.module('tangled-app',['ngResource'])
    .controller('tangledCtrl', function($scope, $resource){
        var Customer = $resource('http://localhost\\:8080/tangled/rest/customers');
        
        $scope.appName = "Tangled App";             // App name
        $scope.customers = Customer.query();        // Calls our Resteasy-Tapestry REST API /GET customers
    })
........

The script basically just means that I'm working with a Angular app called "tangled-app" and then AngularJS inits to also load the Angular-Resource library so we can use the $resource variable. The whole thing then just hinges on the var Customer = $resource('http://localhost\\:8080/tangled/rest/customers'); line. Think of this line as a "promise", it promises to return data when you call the query or equivalent function.

After the script all you have to do is add the tangled-app value to the ng-app directive and the tangledCtrl to a ng-controller:
 <!DOCTYPE html>  
 <html ng-app="tangled-app">  
   <head>  
......... 
   </head>  
   <body>  
     <div class="container" ng-controller="tangledCtrl">  
       <div class="row-fluid">  
         <h3>Abstract</h3>  
         <p>This a simple customer ajax app with   
           <a href="http://tynamo.org/tapestry-resteasy+guide">Tapestry-resteasy</a> as the backend   
           and <a href="http://angularjs.org/">AngularJS</a> on the front. It also uses   
           <a href="http://twitter.github.io/bootstrap/">Twitter-Bootstrap</a>.</p>  
       </div>  
       <div class="customer-table">  
         <table class="table table-striped table-bordered">  
           <thead>  
             <tr>  
               <th>#</th>  
               <th>Name</th>  
               <th>Address</th>  
               <th>City</th>  
               <th>Country</th>  
               <th>Code</th>  
               <th>Credit Limit</th>  
             </tr>  
           </thead>  
           <tbody>  
             <tr ng-repeat="customer in customers">  
               <td>{{customer.customerNumber}}</td>  
               <td>{{customer.customerName}}</td>  
               <td>{{customer.addressLine1}} {{customer.addressLine2}}</td>  
               <td>{{customer.city}}</td>  
               <td>{{customer.country}}</td>  
               <td>{{customer.postalCode}}</td>  
               <td>{{customer.creditLimit}}</td>  
             </tr>  
           </tbody>  
         </table>  
       </div>  
     </div>  
........
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>  
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular-resource.js"></script>  
     <script type="text/javascript" src="js/tangled.js"></script>  
   </body>  
 </html>

BTW, if you're using Chrome, you'll get an "access-control-allow-origin" error. To fix this and allow you to continue developing in a local machine then just run Chrome with --disable-web-security. Don't do this though when browsing the internetz.

Tuesday, July 2, 2013

Designing with the end in mind: tuktuk style

This is part 4 of my Resteasy Tapestry with AngularJS tutorial. This is the design part of the tutorial. Now a days, what good is a web applications if it can't look good. I'm not a UI design expert by any kind of measure, in fact, I pretty much suck at it. So, I'm using somebody else's stuff to get me to look half decent, hence I'm using Javi Jimenez's tuktuk CSS framework.


Tapestry5 Layout sources
In Tapestry, the look of the website is a layout component. It works like pretty much like any other templating system you probably have seen or tried. You have a main template where the smaller page specific templates are "added" into. I have also write about tapestry layouts in a previous tutorial.

The first thing we have to do is add the tuktuk assets like the style sheets and scripts. 

1. Copy the style sheets into the layout folder. You should be adding 3 stylesheets: tuktuk.css, tuktuk.icons.css and tuktuk.theme.css

2. If the folder doesn't exist yet, create a "js" folder in the layout folder and copy the tuktuk.js file into it.

With the assets in place, we need to tell Tapestry5 about it. Open up the layout.java source file in the components folder. And right on top of the class declaration is an @import annotation, this what we change so our Tapestry webapp will be using the tuktuk assets. Change it to:

@Import( stylesheet = {"context:layout/tuktuk.css","context:layout/tuktuk.icons.css",
                       "context:layout/tuktuk.theme.css","context:layout/layout.css"},
        library = {"context:layout/js/tuktuk.js"})

That layout.css stylesheet is your own stylesheet seperate from the tuktuk.css. It's a bad idea to add your own style rules to the tuktuk.css. It's better to use your own.

The last step is to edit the layout.tml. The layout.tml is a very simple HTML template file so it should fairly easy to understand. It's a HTML file for christ sakes!

Saturday, June 15, 2013

Easy restful services with tapestry and tynamo-resteasy

This is part 3 of my Resteasy Tapestry with AngularJS tutorial. We will be building the restful api for this tutorial/project. I'll be trying to keep it simple with just CRUD equivalents like GET,  POST, PUT, and DELETE.

First thing first, we will be using Tynamo Resteasy for building the api. We could build our own from scratch but why re-invent the wheel? To add it, you will leverage Maven. Open up your POM file which should be on the root portion of the project and edit it:


<dependency>  
      <groupId>org.tynamo</groupId>  
      <artifactId>tapestry-resteasy</artifactId>  
      <version>0.3.1</version>  
 </dependency>    
 <dependency>  
      <groupId>org.jboss.resteasy</groupId>  
      <artifactId>resteasy-jackson-provider</artifactId>  
      <version>3.0-beta-4</version>  
 </dependency>

We need a JSON marshaller/unmarshaller, hence the resteasy-jackson-provider. We will be working with JSON, no XML. Read the Tynamo-resteasy guide for clarification on this. Now, simply clean and build the project and let Maven do its thing and get all them jars.

The next step is to create the Tapestry service that will respond to AJAX calls. In keeping with Tapestry convention, I'm putting this service inside a package. I called mine: com.demo.tangled.rest. So, it doesn't look so cluttered, I'm just showing the GET method of our restful API inside this service.
package com.demo.tangled.rest;

import com.demo.tangled.dao.contactsDAO;
import com.demo.tangled.entities.Contacts;
import org.apache.tapestry5.ioc.annotations.Inject;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import java.util.List;

@Path("/customers")                     // URL for API call     
public class contactsResource{
    
    @Inject                             // Get that DAO service
    private ContactsDAO contactsDAO;
    
    @GET
    @Produces({"application/json"})     // Set output format to JSON
    public List<contacts> getAllContacts(){
        return contactsDAO.getAll();
    }
    .....    
}

The interesting parts of the code are the annotations. The first annotation, @Path, is the URL for API which is appended to rest sub-domain path. So, the address of this resource is http://localhost:8080/tangled/rest/customers if this was running on a local development machine. The other request methods like POST, PUT and DELETE are written in the same manner as the getAllContacts method. Notice the @GET annotation.

I have already wrote about how to make DAO services in my previous Tapestry5 tutorial.

Thursday, June 6, 2013

Our Database: Dropping MySQL for MariaDB

This is part 2 of my Resteasy Tapestry with AngularJS tutorial. We will be fleshing out the database that we will be using for this tutorial/project.

I will be using MariaDB in this. I could use MySQL but ever since Oracle took it over, I've been slightly uncomfortable in using/recommending it. Besides, MariaDB is a drop-in replacement, so any code you wrote (or will write) for MySQL will be OK with a MariaDB database.

As not to be bogged down by database design details, we'll just have a 1 table database for Contacts.

As for our management tool, we will be using Netbeans. Yes, Netbeans. (I'll let that sink in.)

You can manage your MariaDB database in Netbeans just by registering it and running queries against it. And it does have a few GUI features like a 'Create-Table' wizard. To register your MariaDB database(I'm assuming that you have Netbeans and MariaDB installed already) do the following:


  1. Download the java-client driver  
  2. In Netbeans, go to the "Services" tab, right-click on it and select "New Connection"
  3. Pick new driver
  4. On the new window, locate the java-client driver you just downloaded
  5. Set the driver class to: org.mariadb.jdbc.Driver
  6. Pick a name for this new connection
You should be then able then to connect to your MariaDB instance. To test, try executing the command:

create database tangledb;

That should execute without a problem. As for creating a "Contacts" table, that should be fairly straight-forward. Just open up the new tangledb database and on the table folder, right-click and add new table.

As for the columns:
- id (integer, pk)
- firstname (varchar(50), nullable)
- lastname (varchar(50), nullable)
- nickname (varchar(50), not nullable)
- birthday (date)
- mobile (varchar(15), nullable)
- landline (varchar(15), nullable)
- e-mail (varchar(150), nullable)

Click OK and there you have your MariaDB database.

Saturday, June 1, 2013

Creating the project in Netbeans with Maven

Modern software development is partly about the tools you use. Just don't insist yours is better with other programmers unless you want to start a religious war.

I use Maven. Maven is a software project management and comprehension tool. It's easy to install and use and Netbeans, my preferred IDE, can work with it by default unlike the other leading IDE which needs a plugin.  

Once you've installed Maven, you'll need to configure Netbeans to use the installed one unless you want to use the bundled one. You can do that via the menu Tools -> Options -> Java(tab) -> Maven. It should auto-detect the Maven home if you installed Maven correctly. After this, you're pretty much set.

Project from Archetype
Now all you need to do is create our Tapestry5.

Create a new project and choose Maven and then Project from Archetype.

We will be using the quickstart Tapestry5 project to get us rolling fairly quickly. The current version should 5.3.7.

On the "next" window, set the values to the following:
  • Group ID: org.apache.tapestry
  • Version: 5.3.7
  • Artifact ID: quickstart
  • Repository: http://tapestry.apache.org
You should be able to figure out the next page. After you clicked on that Finish button, you should see the your freshly created Tapestry5 project. 

Before you can run a Tapestry5 project, you need to satisfy a sample requirement which is a create a custom  Maven goal. You'll need this if you want to use the Live Reloading feature. I already wrote a how-to on this in an old blog entry. Just do steps 1, 2 and 3. You don't need to do the rest.

The Tapestry5 running
When you're done, you should be able to run the project and be able to open the web application in your favorite browser. See left. 

If you're wondering, I called my project tangled.

Next week, we'll be working on your database.

Resteasy Tapestry with AngularJS tutorial

I have been on a binge with AngularJS and so far I haven't gone to the hospital. And there's Tapestry5. I have been in-love with it for the longest time.

I think its time for a tutorial.

I'm basically gonna build a simple Tapestry-based restful API and use it with AngularJS. It's not that hard as it sounds. We'll be using Netbeans for this.

Here's what I have planned:

Wednesday, May 22, 2013

Android and the case of making app assets

ActionBarSherlock
Let's face it's fun to visualize and design Android apps at first then it goes down hill from there. I mean creating all them icons, gradient backgrounds and other assets is boring and sometimes down right tedious. And you have to it 3 times! So why not use a generator?

I have been using this website for a couple of projects: Android Assets Studio.

I'm a big fan of Roboguice (my blog entry) and the ActionBarSherlock which the Android Assets Studio complements. Using the studio allows me to generate the nine patch assets plus associated XML drawables and styles which I then copy straight into my project.

It's also nice that Studio has a bunch of icon generators. I especially find the generic icons pretty hand.

Monday, May 6, 2013

Not your older brother's XAMPP stack

Let's face it, web development has a lot of moving parts: web server, database, various libs and PHP as programming language. And if you're on Windows then your doing it in hard mode. 

I've been using XAMPP but I getting bored with Apache and MySQL. It's time to use something else, learn something new. Who knows, it might be helpful down the road in trolling someone. This is where I found out about WPN-XM. It's an abbreviation of something pretty long, just read about it on their website.

WPN-XM which is the same as XAMPP except it uses Nginx instead of Apache and MariaDB instead of MySQL and it even has MongoDB. Think about it, MariaDB and MongoDB all in a single dev stack. It also have a few tools that any PHP5 programmer will appreciate like Webgrind and XDebug.

This should be interesting.


Friday, May 3, 2013

Personal Note: My country's sometimes sad state of health care

The Philippines is moving up in the world. If you called it a third-world country, then you're dead wrong. We haven't been third-world since the late 1970's. But if you called us a developing country then you're sort of right. Here's a little story of mine living in a developing country.

I have an annoying skin thing called Contact Dermatitis which me or my doctor doesn't seem to know what the trigger is. My doctor has sent a piece of my skin to UP to a Skin Pathologist to confirm it is indeed contact dermatitis. My doctor is excellent, she's an expert in her field and I don't think anyone in the world would be any better. The point is I have access to good doctors and generally decent health care.

Then, my doctor said that I should get a skin patch test to figure out what's the trigger of my dermatitis so I can stop itching. Guess what, it isn't available in Cagayan de Oro but in Davao City, 400 miles south. To make it more "challenging", its only performed in a single hospital: Davao Medical which is now Southern Philippines Medical Center.

I never really understood this. Why the test is available is in Davao city and not in my home town? I have seen the test and it isn't that complicated.

Sometimes you just have to suck it up and deal with the sad state of affairs.

Saturday, April 13, 2013

You're a lazy bastard making a website and you need image placeholders

Yes, you read the title right.

How many times I have needed image placeholder while building website then get hit by lazy. I don't want to be creating image placeholders in Photoshop or Fireworks.

So, Google the Internet to find a service and it did not disappoint: http://placehold.it/

I hope this site stays online. I'm too lazy to find another one.

Monday, April 1, 2013

Code fasta, Fasta, FASTA with zen coding

Zen wunz go fasta!
If you're familiar with Warhammer 40k Orks, then the reference should be appropriate otherwise, WHOOOSH!

What is this zen coding BS then, you might ask? Well, zen coding is something Google came up with to write out HTML faster. Zen is not a technique mind you but rather an editor plugin for your favorite IDE allowing you to write in abbreviations and then expanding it to completed code.
You can basically write shit like this:

div#page>div.logo+ul#navigation>li*5>a

And have it expand to this:

<div id="page">  
     <div class="logo"></div>  
     <ul id="navigation">  
         <li><a href=""></a></li>  
         <li><a href=""></a></li>  
         <li><a href=""></a></li>  
         <li><a href=""></a></li>  
         <li><a href=""></a></li>  
     </ul>  
 </div>

We should be able to see the convention quite easily and as you can see quite convenient in handling with repetitive code. Unless, of course you're someone who like's typing, then that's another thing altogether.

This also works on Less and Sass code among other things. And it also comes as Netbeans plugin which is very nice. Other implementations are also available.



Monday, March 18, 2013

Tapestry5 and JasperReports

Creating "reports" are a fact of life for developers. It's sucky work but necessary. With my Tapestry5 application, I decided to use JasperReports for the following reasons:
  1. It's free
  2. It's easy to use
  3. It has a nice plugin that works inside Netbeans: iReport
To get started, you have to add JasperReports dependency in your POM.xml:

 <dependency>  
   <groupId>net.sf.jasperreports</groupId>  
     <artifactId>jasperreports</artifactId>  
   <version>5.0.1</version>  
 </dependency>  
 <dependency>  
   <groupId>commons-collections</groupId>  
     <artifactId>commons-collections</artifactId>  
   <version>3.2.1</version>  
 </dependency>  

The commons-collections might be needed to fix a transitive dependency error that you might get with Tapestry5 and JasperReports.

The next part is the report template (jrxml) needs to be created. I just put it template in the WEB-INF folder so to access it is: /WEB-INF/reports/report1.jrxml

The report template is a rather rich XML file with a lot of moving parts but it shouldn't be that hard since we do have the iReport plugin to "visually" create the reports. Here is an example: test_jasper.jrxml. And here is a full working example.

The next piece of the puzzle is a custom Tapestry5 StreamResponse for PDF files. The idea is after we generate the report, we are going to send it to the client as a PDF file so they can print it.

 import java.io.IOException;  
 import java.io.InputStream;  
 import org.apache.tapestry5.StreamResponse;  
 import org.apache.tapestry5.services.Response;  
 /**  
  *  
  * @author jaypax  
  */  
 public class PDFStreamResponse implements StreamResponse {  
     private InputStream is;  
     private String filename="default";  
     /**  
      * Constructor  
      * @param is  
      * @param args (http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html  
      */  
     public PDFStreamResponse(InputStream is, String... args) {  
         this.is = is;  
         if (args != null) {  
             this.filename = args[0];  
         }  
     }  
     public String getContentType() {  
         return "application/pdf";  
     }  
     public InputStream getStream() throws IOException {  
         return is;  
     }  
     public void prepareResponse(Response arg0) {  
         arg0.setHeader("Content-Disposition", "attachment; filename="  
                 + filename + ".pdf");  
     }  
 }  

Then we can now add a event handler for that button when clicked sends the report. In my scenario, its inside a onSubmit event. This is on a page class that's populated with services injected via Tapestry's IOC. I also injected the report form as an asset.

    @Property
    private int id;

    @Inject
    @Path(value = "context:WEB-INF/reports/report1.jrxml")
    private Asset ReportForm;
    ....
    ....
    ....
    public StreamResponse onSubmitFromReportForm() throws IOException,JRException{
        InputStream is = ReportForm.getResource().openStream();
       
        JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(someDAO.findAllEntriesById(id));
        
        Map reportParams = new HashMap();
        reportParams.put("TITLE", "SOME REPORT TITLE");

        JasperDesign reportDesign = JRXmlLoader.load(is);
        JasperReport reportCompiled = JasperCompileManager.compileReport(reportDesign);
        JasperPrint reportPrinted = JasperFillManager.fillReport(reportCompiled, reportParams,ds);
           
        ByteArrayInputStream bais = new ByteArrayInputStream(JasperExportManager.exportReportToPdf(reportPrinted));
        
        return new PDFStreamResponse(bais, "Some Report");
    }

Notice the PDFStreamResponse as the return object, without that then browser will mishandle the return stream.

Turning this into a service shouldn't be that hard which I will probably do in a coming iteration.

Tuesday, March 12, 2013

Timed redirect without the php, javascript fuzz

Having worked on a few MVC projects in different languages like PHP, C# and Java, there always that "thank you" or "success" page you show after successful operation like an insert or update. Often these pages are automatically redirected to some URL after a set amount of time, normally 10 - 15 seconds. Normally, I use javascript; Something like this:

 <script type="text/JavaScript">  
 <!--  
 setTimeout("location.href = 'http://google.com';",1000);  
 -->  
 </script>  

It works but then I found out there's an easier way to do this via a HTML meta tag. Wikipedia explains it here. This one just automatically redirects you to google.com after 10 seconds.

<meta http-equiv="refresh" content="10;URL='http://google.com/'">  

It does have drawbacks but it works and I don't have to really concern myself if the browser's javascript is on or off.

Tuesday, March 5, 2013

Tapestry 5.3 and the case of Twitter-Bootstrap disabled attributes

Making Tapestry5 use Twitter-Bootstrap as its style is quite easy but not everything is as it seems.

Bootstrap as some nice form style rules. It's quite easy to add them into normal tapestry5 common components. Like if you need some a textfield to look like a "search-query" field then you would write something like:

// Rounded corners
<input t:type="textfield" t:id="keyword" class="search-query" placeholder="Callslip ID"/>  

or if you need a page or event link to look like a button:

// Tapestry5 eventlink styled as a button via Bootstrap
<a t:type="eventlink" t:event="add" class="btn brn-primary" href="#">Add 1</a>  

But I have recently came across a scenario where I need to display a textfield with data that's by default is uneditable but under certain conditions can be edited. Reading the bootstrap documentation, you have to do something like this:

// As shown in the Bootstrap documentation
<input class="input-xlarge" id="disabledInput" type="text" placeholder="Disabled input here..." disabled>

OK, that should be easy to convert into tapestry5 component and use javascript to enable or disable the field. When done via jquery, removeAttr() or prop(). There's an equivalent to add an attribute.

// Tapestry5 is not happy about disabled attribute
<input class="input-xlarge" id="disabledInput" t:type="textfield" placeholder="Disabled input here..." disabled>

And that's this is where the problem crops up. Tapestry5 doesn't like any unpaired attributes. I'm talking about the disabled attribute at the end of the input element above. Fortunately, Peter Wendorff in the Tapestry mailing-list pointed me to a html microsyntax spec document explaining this unique nuance of html. You have to do a disabled="true" attribute to makeTapestry5 happy.

// How Tapestry5 wants it done
<input disabled="true" class="input-xlarge" t:id="name" t:type="textfield" placeholder="${name}" />
Other ways to write this doesn't work, even if the spec doc says its OK.

  • disabled="" -> doesn't work
  • disabled="disabled" or disabled='disabled' or disabled=disalbed -> also doesn't work
  • disabled -> obviously doesn't work

Saturday, February 23, 2013

CoffeeScript and JQuery

Writing JQuery code with CoffeeScript was bit of a Challenge for me. I sort of had to unlearn my previous coding habits so not to make my CoffeeScript look like JavaScript. With me its more of a coding style problem but overall writing DOM manipulation code with CoffeeScript (with JQuery) is more pleasant that I expected. It's certainly shorter.

Let's start with the HTML doc that we will be playing with.

<html>  
   <head>  
     <title></title>  
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
     <link href="css/mystyle.css" rel="stylesheet">  
     <script src="js/jquery-1.9.1.js" type="text/javascript"></script>  
     <script src="js/Control.js" type="text/javascript"></script>  
   </head>  
   <body>  
     <div id="hoverElem">Hover over <a href="#" id="target">this</a> to show message</div>  
     <div id="message" class="hidden">I be rollin' with CoffeeScript and   
     they be hatin'!</div>  
   </body>  
 </html>   

It's quite easy to figure out what I'm trying to do here. I have a target "this" when you hover over it, it shows some kind of message.

The CSS is also quite simple.

root { 
    display: block;
}

#message{
    border: 1px solid #9966cc;
    margin: 10px;
    padding: 10px;
    text-align: center;
}

.hidden{
    display: none;
}

The real work is again done with our CoffeScript file.

$ ->
  $('#target').mouseover (e) -> $('#message').removeClass 'hidden' 
    
  $('#target').mouseout (e) -> $('#message').addClass 'hidden'

The first line "$ ->" is equivalent to the document.ready() or $.function() for JQuery. The next two lines are where the work is done. The syntax is quite compact to handle a mouseover and mouseout events. The (e) element is the event parameter. The arrow part leads to inside of the function with the removeClass and addClass methods.

The sample here is quite trivial but it does show the basics of using CoffeeScript with JQuery. A couple of more weeks (or months) of puttering around with it I think I can get pretty good with CoffeeScript and another popular JavaScript libraries like underscore, knockout or maybe gmap.

Can't wait to try this out with a real project. Let's see if Odesk got some. *grin*

Wednesday, January 30, 2013

CoffeeScript prototypes and classes

CoffeeScript tries to overcome the verbosity of JavaScript's prototype and class syntax. Here's how JavaScript does it:

function foo(name){
    this.name = name;
}

foo.prototype.bar = function(){
    console.log('Status is fubar!');
}

o = new foo('John');
o.bar();

That's a bit more of characters to type. If you take a look at how CoffeeScript does it:

foo = (@name) ->                 # the @name is same as writing this.name = name

foo::bar = ->                    # the '::' is the prototype keyword
  console.log 'Status is fubar'
  
o = new foo('John')

console.log o.name
o.bar()

But all this prototype business can be moved into a more object-oriented style using CoffeeScript's class constructs.
class Fish
  constructor: (@name) ->               # gets transformed into a simple JavaScript constructor
  swim: (direction) -> console.log @name + 'is swimming ' + direction # prototype; notice the @name which is this.name
                                                                      # and the direction is a function parameter
  
fish = new Fish('Nemo')   # play around with fish object
console.log fish.name
fish.swim('north')

I sort of subscribe to shorter code is cleaner code. That's why I'm liking CoffeeScript so far.

Sunday, January 27, 2013

CoffeeScript control structures

Coffeescript has really few control structures. Most of the loops, for example, can be written as comprehensions over arrays, objects and ranges. Comprehensions should be able to handle most places where you otherwise would use a loop, each/forEach, and map.

For example:
fruits = ['Apple', 'Orange', 'Banana', 'Grapes']
console.log fruit for fruit in fruits

Would result in this JavaScript:
var fruit, fruits, _i, _len;

fruits = ['Apple', 'Orange', 'Banana', 'Grapes'];

for (_i = 0, _len = fruits.length; _i < _len; _i++) {
  fruit = fruits[_i];
  console.log(fruit);
}

The real work happens at the console.log fruit for fruit in fruits line. It calls the console.log function for each fruit in fruits.

CoffeeScript also has a few cool tricks in working ranges. They are quite handy if you need row numbers for tables. Here is an example:

tableRowNum = (num for num in [10..1])  
console.log c for c in tableRowNum

The only real loop construct that CoffeeScript has is the while loop. But its better than JavaScript's because it can be used as an expression. It also works nicely with another keyword: the until keyword. For all intents is a while not loop in javascript.

# Econ 101
if this.studyingEconomics
  buy()  while supply > demand
  sell() until supply > demand

So far, CoffeeScript is surprising me. It's certainly not boring me.

Saturday, January 5, 2013

CoffeeScript data types and functions

CoffeeScript's golden rule is "It's just JavaScript". As seen, in the previous entry, it compiles to a 1-to-1 equivalent of JavaScript. This also means that CoffeeScript's data types are also limited to what JavaScript has. These are strings, numbers, booleans, arrays, objects, nulls and undefined values. But CoffeeScript has a couple of pretty cool stuff baked for data types, especially strings. Here is a pair of examples:

name = "Jay" // CoffeeScript doesn't need a var prefix 
greet = "Hello, #{name}" // String interpolation
                         // Result: Hello, Jay

grade = 88.43 
withHonors = 100 <= grade > 85 // chained comparisons
                               // Result: true

songNotes = ["do", "re", 
             "mi", "fa", 
             "so"] // just an array but CoffeeScript knows how to deal with new lines

Also, CoffeeScript takes care to make sure that all of your variables are properly declared within lexical scope — you never need to write var yourself.

There are a lot more cool/useless stuff baked into CoffeeScript variables but to really use them you need functions. In JavaScript, functions are needed for almost anything. Its the same in CoffeeScript. CoffeeScript just declares functions differently - more lisp/scala like.
// Here is a function without a paramter
foo -> alert('foobar')  // foo is the function name
                        // the part after the "->" is the body of the function

// Here is a function with a parameter
square = (x) -> x * x  

// Here is a function with default value on a parameter
fill = (container, liquid = "coffee") ->
  "Filling the #{container} with #{liquid}..."