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!