Sunday, December 1, 2013

AngularJS and select statements using resources

I would expect from a good framework like AngularJS that it integrates their methods to play together nicely to solve problems such as the issue with the select statement that only supports referential equality which is not working with resources ($resource) as data source. In the edit case where an object in the ng-model is matched to the resource object it will fail. It took me about 4 hours analyze the problem and then find the ngyn select directive that solves the problem with an own select directive. I'd like to thank the authors for this nice plugin and hope it will find it's way in to the AngularJS code eventually.

Select Extensions

The AngularJS select directive lacks the capability to select an existing option based on anything other than referential equality. The ngynSelectKey module extends select with the capability to specify how items should be compared. This makes it trivial to match an item in the select list with a value being returned, for example from a query.

Usage is simple, just supply a value within a key attribute, this will typically be a property name but it can be anything which will resolve using $scope.$eval(), such as a function on each attribute.

HTML
<select ng-model="user.role" 
        ng-options="r.name for r in user.availableRoles" 
        key="id">
</select>
JavaScript
  $scope.user = {};
  $scope.user.role = { id: 1, name: 'Administrator' };
  $scope.user.availableRoles = Roles.query();
  • You can find the description here
  • You can find the source here

Integrate the plugin

To integrate the plugin I have downloaded the select-key.js file and added it to my lib directory in which also the AngularJS libraries are located.

Then I added the file to my index.html page.

<script src="../lib/angular120/angular.js"></script>
<script src="../lib/angular120/angular-route.js"></script>
<script src="../lib/angular120/angular-resource.js"></script>
<script src="../lib/ngyn/select-key.js"></script>

And as last step added the module in to my app (app.js) in my case.

angular.module('myApp', ['ngRoute',
        'ngynSelectKey',
        'errorHelper',
        'formHelper',
        'fileHelper',
        'eaValidators',
        'user',
        'vendor',
        'card'])

Tuesday, November 5, 2013

Configure Fedora 19 Desktop

Word in advance

After several years I wanted to try Linux as a desktop again and was quite amazed how good I got along.

I have tried Ubuntu but I soon discovered that the evil of marketing got over them and they are turning Ubuntu in to a Windows Clone. Not only that. They are sending all queries made with their Unitiy search to Amazon and other third parties. ALL queries. Even those made on the file system. Do you really want Amazon to see what you are searching on the file system? After trying to turn the feature off by deinstalling certain packages it killed my desktop and I had to re-install it over the console. Additionally I had problems with sound drivers and the Unity Desktop is far from being user friendly. So what is the conclusion of all this?

As soon the money is invested in to Marketing instead of Product Management the quality of products drops dramatically. The revenue and maybe also the profit will rise short term but many of these products will somewhen hit the ground hard.

I tried with Fedora and the Gnome Desktop and just stuck to it as it is running rock solid and has good driver support. The only lack are the Wireless network drivers. But this is the case for all Linux distributions.

Install Vim

sudo yum install vim

Install dconf-editor

Install the dconf-editor over the Software Center.

Set Logout Link

You can define that the logout link is displayed in the menu on the top of the right hand side. Open the dconf-editor and choose org -> gnome -> shell. Then tick always-show-logout.

Installing Flash

http://fedoraproject.org/wiki/Flash

Install Flash Browser Plugin

Open a terminal window and install flash.
sudo yum install http://linuxdownload.adobe.com/adobe-release/adobe-release-x86_64-1.0-1.noarch.rpm -y
Add flash plugin to use with browsers.
sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-adobe-linux
sudo yum install flash-plugin -y

Install Shutter

Shutter is a screenshot application for gnome. You can install it over the Software Center.

Transparent Terminal Window

By default the gnome terminal window does not support transparent background. To add this feature again you can use devilspie.
sudo yum install devilspie
mkdir ~/.devilspie
vim ~/.devilspie/terminal-opacity.ds
(if
  (matches (window_name) "Terminal")
  (opacity 85)
) 

Add devilspie to Gnome Startup

Open a terminal window and start gnome-session-properties.
gnome-session-properties
Click on to the Add button to create a new session startup application and add devilspie as displayed on the picture.

Resources

Install Google Chrome

Firefox is my most beloved Browser. But sometimes I have problems opening content such as the Swiss News Videos. For this I use Chrome that is working in such cases. Install Chrome over the Chrome Website.

Install Wuala

Wuala is a secure cloud storage service such as Dropbox. The great thing about it is that it splits the files in chunks, encrypts the chunks before uploading and uploads the chunks to servers in Switzerland, Germany and England. So it at least looks pretty secure. You can install Wuala over the Wuala Website. To start Wuala when you login you can add Wuala to the startup applications.

Name: Wuala
Command: wuala -nogui login <your login> <your password>: "$@"
Description: Wuala

Install MongoDB for Dev

tar -xvzf mongodb-linux-x86_64-2.4.7.tgz
sudo mv mongodb-linux-x86_64-2.4.7 /opt/mongodb

Add MongoDB as Development Database to Gnome Startup

Click on to the Add button to create a new session startup application and add MongoDB with following parameters:

Name: MongoDB
Command: /opt/mongodb/bin/mongod --dbpath /tmp --setParameter textSearchEnabled=true
Description: MongoDB


Add MongoDB bin directory to PATH

Edit /etc/profile and add following line before the general export command:
PATH=$PATH:/opt/mongodb/bin # <- Add this line
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL

Install Oracle Java 7 SDK

http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html
cd /etc/alternatives/
sudo rm java
sudo rm javaws
sudo rm javac
sudo rm jar
sudo rm libnpjp2.so

sudo ln -s /usr/java/latest/bin/java .
sudo ln -s /usr/java/latest/bin/javaws .
sudo ln -s /usr/java/latest/bin/javac .
sudo ln -s /usr/java/latest/bin/jar . 
sudo ln -s /usr/java/latest/jre/lib/amd64/libnpjp2.so .
java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
vim /etc/profile
export JAVA_HOME="/usr/java/latest"

Install Apache Maven

tar -xvzf apache-maven-3.1.1-bin.tar.gz
sudo mv apache-maven-3.1.1-bin /opt/apache-maven
vim /etc/profile
export M2_HOME=/opt/apache-maven

Install Intellij Idea

tar -xvzf ideaIU-12.1.6.tar.gz
sudo mv ideaIU-12.1.6 /opt/idea

Create .desktop file

Create a file in ~/.local/share/applications/idea.desktop:
[Desktop Entry]
Comment=Intellij Idea
Terminal=false
Name=Idea
Exec=/opt/idea/bin/idea.sh
Type=Application
Icon=/opt/idea/bin/idea.png

Install HPLip

Download hplip http://hplipopensource.com/hplip-web/downloads.html restart Install hplip-gui

Install KeePass 2

Install Mono
sudo yum -y install mono-core
sudo yum -y install mono-devel
Download the KeePass Zipfile (not the installer) from http://keepass.info/download.html in to ~/Downloads.
sudo yum install wget
cd ~/Downloads
mkdir keepass
mv KeePass-2.24.zip keepass
cd keepass
unzip KeePass-2.24.zip
wget http://upload.wikimedia.org/wikipedia/commons/1/19/KeePass_icon.png
cd ..
sudo mv keepass /opt/
Create keepass.desktop file /usr/share/applications/
sudo vim keepass.desktop
[Desktop Entry]
Name=KeePass
Exec=mono /opt/keepass/KeePass.exe
Icon=/opt/keepass/KeePass_icon.png
Categories=Other
Type=Application

Sunday, September 22, 2013

Creating a global http error handler for your AngularJS app

Please note that this is deprecated:

See https://github.com/angular/angular.js/blob/master/CHANGELOG.md#1.1.4 and search for responseInterceptors, its deprecated.

If you're pissed like me about frameworks changing their methods every 6 months don't use Angular!



If you are using AngularJS with REST then it comes in handy to have a global http error handler that will intercept the http status message and display a message on the page accordingly. Therefore I have tweaked and created following error handler based on some examples found on the net.

As you can see the showMessage function will display the messages. The first parameter that can be parsed is the error message, the second parameter is a css class name and the third parameter is the time in miliseconds to display the message.

$httpProvider contains http defaults and is also able to intercept all http responses. So push a function to this interceptor which will listen on http return status messages. If there is a return status message we will trigger a message to be displayed on our Angularjs index.html page.

lib/xx/xx-http-error-handling.js
/**
 * @ngdoc overview
 * @name xx-http-error-handling
 * @description
 *
 * Module that provides global http error handling for apps.
 *
 * Usage:
 * Hook the file in to your index.html: <script src="lib/xx/xx-http-error-handling.js"></script>
 * Add <div class="messagesList" app-messages></div> to the index.html at the position you want to
 * display the error messages.
 */
(function() {
  'use strict';
  angular.module('xx-http-error-handling', [])
    .config(function($provide, $httpProvider, $compileProvider) {
      var elementsList = $();

      // this message will appear for a defined amount of time and then vanish again
      var showMessage = function(content, cl, time) {
        $('<div/>')
          .addClass(cl)
          .hide()
          .fadeIn('fast')
          .delay(time)
          .fadeOut('fast', function() { $(this).remove(); })
          .appendTo(elementsList)
          .text(content);
        };

        // push function to the responseInterceptors which will intercept 
        // the http responses of the whole application
        $httpProvider.responseInterceptors.push(function($timeout, $q) {
          return function(promise) {
            return promise.then(function(successResponse) {
              // if there is a successful response on POST, UPDATE or DELETE we display
              // a success message with green background
              if (successResponse.config.method.toUpperCase() != 'GET') {
                showMessage('Success', 'xx-http-success-message', 5000);
                return successResponse;
              }
            },
            // if the message returns unsuccessful we display the error 
            function(errorResponse) {
              switch (errorResponse.status) {
                case 400: // if the status is 400 we return the error
                  showMessage(errorResponse.data.message, 'xx-http-error-message', 6000);
                  // if we have found validation error messages we will loop through
                  // and display them
                  if(errorResponse.data.errors.length > 0) {
                    for(var i=0; i<errorResponse.data.errors.length; i++) {
                      showMessage(errorResponse.data.errors[i], 
                        'xx-http-error-validation-message', 6000);
                    }
                  }
                  break;
                case 401: // if the status is 401 we return access denied
                  showMessage('Wrong email address or password!', 
                    'xx-http-error-message', 6000);
                  break;
                case 403: // if the status is 403 we tell the user that authorization was denied
                  showMessage('You have insufficient privileges to do what you want to do!', 
                    'xx-http-error-message', 6000);
                  break;
                case 500: // if the status is 500 we return an internal server error message
                  showMessage('Internal server error: ' + errorResponse.data.message, 
                    'xx-http-error-message', 6000);
                  break;
                default: // for all other errors we display a default error message
                  showMessage('Error ' + errorResponse.status + ': ' + errorResponse.data.message, 
                    'xx-http-error-message', 6000);
              }
              return $q.reject(errorResponse);
            });
          };
        });

        // this will display the message if there was a http return status
        $compileProvider.directive('httpErrorMessages', function() {
          return {
            link: function(scope, element, attrs) {
              elementsList.push($(element));
            }
          };
        });
      });
})();
You probably want to style the color of your message. If the message is an error it will be displayed in red. If the message is a success it will be displayed in green.

css/xx-http-error-handling.css
/* display error message styled in red */
.xx-http-error-message {
    background-color: #fbbcb1;
    border: 1px #e92d0c solid;
    font-size: 12px;
    font-family: arial;
    padding: 10px;
    width: 702px;
    margin-bottom: 1px;
}

.xx-http-error-validation-message {
    background-color: #fbbcb1;
    border: 1px #e92d0c solid;
    font-size: 12px;
    font-family: arial;
    padding: 10px;
    width: 702px;
    margin-bottom: 1px;
}

/* display success message styled in green */
.xx-http-success-message {
    background-color: #adfa9e;
    border: 1px #25ae09 solid;
    font-size: 12px;
    font-family: arial;
    padding: 10px;
    width: 702px;
    margin-bottom: 1px;
}
Now all that is left is to add the tag defined by the directive to your index.html file.

index.html
<!doctype html>
<html lang="en" ng-app="myApp">
  <head>
    <meta charset="utf-8">
    <title>YourApp</title>
    <link rel="stylesheet" href="css/app.css"/>
    <link rel="stylesheet" href="css/style.css"/>
    <link rel="stylesheet" href="css/xx-http-error-handling.css"/>
  </head>
  <body>

    <!-- Display top tab menu -->
    <ul class="menu">
      <li><a href="#/user">Users</a></li>
      <li><a href="#/vendor">Vendors</a></li>
      <li><xx-logout-link/></li>
    </ul>

    <!-- Display errors from xx-http-error-handling.js -->
    <div class="http-error-messages" http-error-messages></div>

    <!-- Display partial pages -->
    <div ng-view></div>

    <!-- Include all the js files. In production use min.js should be used -->
    <script src="lib/jquery203/jquery-2.0.3.js"></script>
    <script src="lib/angular114/angular.js"></script>
    <script src="lib/angular114/angular-resource.js"></script>
    <script src="lib/xx/xx-http-error-handling.js"></script>
    <script src="js/app.js"></script>
    <script src="js/services.js"></script>
    <script src="js/controllers.js"></script>
    <script src="js/filters.js"></script>
  </body>
</html>
Last but not least you'll have to hook the module in to your app module so that it will be noticed by AngularJS.

js/app.js
angular.module('myApp', ['xx-http-error-handling'])
  // Define routing
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/login', {templateUrl: 'partials/login.html'});
    $routeProvider.when('/user', {templateUrl: 'partials/user.html', controller: UserCtrl});
    $routeProvider.when('/vendor', {templateUrl: 'partials/vendor.html', controller: VendorCtrl});
    $routeProvider.otherwise({redirectTo: '/login'});
  }]);
Here is the JSON output of an error message in case there was an error. As you can see there is an "errors" array that will display validation errors. If there are validation errors and the status is 400 then the validation errors will be displayed each by a single "showMessage" function.

Basically the validation errors should never pop up because we check the validation on client side already. But it is easy for someone to bypass the client side validation and therefore the validation also has to happen on the server side. The messages can help you in case you have forgotten to implement a client validation method. You will then be presented with the error from the server side.

{
  "status":400,
  "code":0,
  "message":"Bad Request",
  "developerMessage":"Validation failed for argument at index 0 in method: ...",
  "moreInfo":null,
  "errors":["Firstname can't be empty", "E-Mail Adress is invalid"]
}

Creating re-usable libraries for your project with Angularjs

There are several ways to structure your code in AngularJS and there is no right or wrong. When you start working with AngularJS I assume that you start by checking out the Angular Seed Project or using Yeoman. However at some point you will want to create libraries or widgets that you want to store in one place for re-use in other projects. For example the "lib" directory.

Examples could include:
  • Global error handler (lib/xx/xx-global-error-handler.js)
  • Authorization (lib/xx/xx-authorization.js)
  • File Upload (lib/xx/xx-file-upload.js)
You can then include these files in to your index.html like this:
<script src="lib/angular.js"></script>
<script src="lib/xx/xx-global-error-handler.js"></script>
<script src="lib/xx/xx-authorization.js"></script>
<script src="lib/xx/xx-file-upload.js"></script>
It is considered as good practice to use a two letter or more letter prefix. For example the starting letters of your surname and name or the first and last letter of your company name. In my case displayed as "xx". This helps to prevent clashes with other files and variables or names you use in your project. I also add the prefix to the name of my controllers, directives and variables.

lib/xx/xx-my-module-name.js
/**
 * @ngdoc overview
 * @name xx-my-module-name
 * @description
 *
 * Your module description goes here
 */
(function() {
  'use strict';
  angular.module('xx-module-name', [])
    .config(['$http',function($http) {
    }])
    .controller('XXMyCtrl', ['$http',function($http) {
    }])
    .directive('xx-my-directive', ['$http', function($http) {
    }]);
})();
Once your module is finished and you added it to the index.html file you'll also have to link it to your main app.js.
angular.module('myApp', ['xx-module-name'])
  // Define routing
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/login', {templateUrl: 'partials/login.html'});
    $routeProvider.when('/user', {templateUrl: 'partials/user.html', controller: UserCtrl});
    $routeProvider.when('/vendor', {templateUrl: 'partials/vendor.html', controller: VendorCtrl});
    $routeProvider.otherwise({redirectTo: '/login'});
  }]);
Like this you can start to plugin your own library sets as required.

General Tips on structuring your code

Personally I have started to also put normal code in to a similar fashion. If I for example need code to handle a Vendor then I'll put everything such as controllers, directives, filters and so on that are related to the vendor in to a file called vendor.js. First of all it is very easy to find what you are looking for and you don't fill up a file with several different controllers or directives in which you have to search for the right controller or directive again.

Monday, July 1, 2013

Spring & MongoDB Repository

Different ways of using spring-data mongodb repository queries

Basic autogenerated queries

With spring-data you can use basic queries such as displayed below:

@Repository
public interface UserRepositoryIf extends MongoRepository {
  User findByEmail(String email);
  List<User> findByEmailLike(String email);
  List<User> findByEmailOrLastName(String email, String lastName);
}
Spring will automatically generate a JSON query based on the Syntax use use. More information about basic queries can be found in the Reference Manual. These queries are ok for basic queries and CRUD functionality. But when it comes to advanced queries then you'll see that you'll end up in a dead end very quickly.

Using queries with @Query annotation

One possibility to do advanced queries is to add the @Query annotation and work with JSON based queries. This enables you to use the full power of the MongoDB Json query language. You can parse parameters as ?0 (for first parameter), ?1 (for second parameter). In this example ?0 will contain the contents of the variable "searchText".

@Repository
public interface UserRepositoryIf 
      extends MongoRepository<User, String> {

  @Query("{\"$or\" : [" + 
    "{ \"email\" : " + 
      "{ \"$regex\" : ?0, \"$options\" : \"i\"}} , " +
    "{ \"firstName\" : " +
      "{ \"$regex\" : ?0, \"$options\" : \"i\"}}, " +
    "{ \"lastName\" : " +
      "{ \"$regex\" : ?0, \"$options\" : \"i\"}}]}")
  List findByEmailOrFirstNameOrLastNameLike(String searchText);
}
Using this we can create complex queries and have the full power of the MongoDB JSON language. However it is not type safe (mistakes in the syntax can happen very easy) and it is bound to the JSON query language of MongoDB. If you want to use another database you'll have to adjust quite a lot of code.

Using MongoTemplate

A question on Stackoverflow when to use mongoTemplate or Repositories actually resulted in a reply I liked. One of the developers of Spring pointed out that it is possible to mix queries based on the requirements by adding custom interfaces and implementations. He suggested that one should start with basic queries and as soon the queries get more complex add a custom interface and implementation to enhance the functionality with MongoTemplate. Here is the Stackoverflow question.
So if you for example have a repository called UserRepositoryIf you would add an interface called UserRepositoryIfCustom and an UserRepositoryIfImpl class. Note that the name of the interface has to be "Custom" at the end of the custom interface and for the implementation class it is expected that it is named "Impl" at the end of the class. If you use other endings it might fail.

@Repository
public interface UserRepositoryIf 
      extends MongoRepository<User, String>, 
          UserRepositoryIfCustom {
  // Basic queries
  User findByEmail(String email);
  List findByEmailLike(String email);
  List findByEmailOrLastName(String email, String lastName);
  List findByEmailOrFirstNameLike(String email, String firstName);
}
public interface UserRepositoryIfCustom {
  // Advanced query
  List<User> 
    searchByEmailOrFirstNameOrLastName(String searchPattern);
}
public class UserRepositoryIfImpl 
      implements UserRepositoryIfCustom {

  @Autowired
  private MongoTemplate mongoTemplate;
  private Class<User> clazz = User.class;

  @Override
  // Advanced query implementation
  public List<User> 
      searchByEmailOrFirstNameOrLastName(String searchPattern) {
    Query query = new Query();
    query.addCriteria(new Criteria().orOperator(
      Criteria.where("email").regex(searchPattern,"i"),
      Criteria.where("firstName").regex(searchPattern,"i"),
      Criteria.where("lastName").regex(searchPattern,"i")
    ));
    return mongoTemplate.find(query, clazz);
  }
}
As you can see like this you have a clear separation between the basic queries and the more advanced MongoTemplate queries. This is what I suggest to use and is also suggested by Spring. More information regarding MongoTemplate can be found in the Reference Manual.

QueryDSL

QueryDSL is quite advanced and totally type safe. It is another possibility how you can query MongoDB. And as you might already guess you can also extend the UserRepository interface. Even if this is quite advanced and supports different databases as backends I do not use it mainly because additional dependencies are necessary and it makes use of APT. If you want to use it please refer to the Reference Manual.

Tuesday, May 7, 2013

Testing REST requests to a Spring MVC backend

Download WizTools RestClient and start it

You can download the WizTools rest client over following site: Google Project.

I have just downloaded the jar.

To start the client I executed the following command:

java -jar restclient-ui-3.1-jar-with-dependencies.jar

Setting loglevel in logback.xml

To actually see what Spring is doing it is necessary to set the web.servlet.mvc log level to TRACE. Only then Spring is actually revealing what is happening under the hood with the json jackson converter and also displays what went wrong if the RequestBody couldn't be processed.

<configuration>
  <contextListener 
   class="ch.qos.logback.classic.jul.LevelChangePropagator">
    <resetJUL>true</resetJUL>
  </contextListener>

  <!-- To enable JMX Management -->
  <jmxConfigurator/>

  <appender name="STDOUT" 
   class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>
        %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
      </pattern>
    </encoder>
  </appender>

  <logger name="com.eerra.cardkeeper" level="INFO" />
  <logger name="org.springframework" level="TRACE" />
  <logger name="org.springframework.beans" level="WARN" />
  <logger 
   name="org.springframework.web.servlet.mvc" 
   level="TRACE" />

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>

</configuration>

Pitfall 400 Bad Request

Without setting TRACE on web.servlet.mvc it will be impossible to debug errors on the interface. For example I have single-quoted my attributes and values which just resulted in a 400 Bad Request:

{
  'email': 'test@test.com',
  'firstName': 'Testfirst',
  'lastName': 'Testlast'
}
After enabling TRACE I have seen following message in the Spring log:
org.springframework.http.converter.
HttpMessageNotReadableException: 
Could not read JSON: Unexpected character (''' (code 39)): 
was expecting double-quote to start field name
at [Source: org.eclipse.jetty.server.HttpInput@69663655; 
line: 2, column: 3]; 
nested exception is org.codehaus.jackson.JsonParseException: 
Unexpected character (''' (code 39)): 
was expecting double-quote to start field name
at [Source: org.eclipse.jetty.server.HttpInput@69663655; 
line: 2, column: 3]
After double-quoting the attributes and values it worked:
{
  "email": "test@test.com",
  "firstName": "Testfirst",
  "lastName": "Testlast"
}

Sunday, April 21, 2013

CORS: Doing the preflight dance with Jetty and Angularjs

Foreword

After giving my best with CORS I'm finally giving up out of following reasons:

  • Browsers behave differently with CORS. This is not usable. One can assume what happens when the next browser upgrade is coming. Debugging, debugging, debugging which just isn't worth the time.
  • Setting Authorization: Basic headers will simply not work. In the W3C specs they have a section for credentials, but they don't loose a word about setting the Authorization header. The only thing that is for sure is that it will be a pre-flight request which other developers warn from using.
  • I have spent about 3 hours every day within 2 weeks to find a way to use CORS with Authorization headers... no luck
  • After that I needed a big mug of beer :) With big mug I mean the equivalent to two bottles of white wine...

Even after these warning signs I believed in my own stupidity until I fell over following sentences:

Funnily enough, when making a CORS request using jQuery, the JavaScript library specifically avoids setting the custom header, along with a word of warning to developers:

// For cross-domain requests, seeing as conditions for a preflight are akin to a jigsaw puzzle, we simply never set it to be sure.

So possibly the best advice, if possible, is to avoid setting the custom header if you don’t want to do the preflight dance.

Otherwise good luck my friend, I hope this has helped!

This boosted my self confidence again seeing that also other people went to the asylum :) But I also found it a petty that I can't use Basic Authentication for cross domain requests. So my next plan is to try solving the issue with tokens or simply not using cross origin requests which has the limitation that I can't separate the client from the backend which makes it less scalable then I wanted my software to be.

Please note that currently development is my hobby. I write these sentences primarily for myself so that I don't repeat mistakes in the next project. I'm happy if my writing helps some people and I'm also happy to get feedback and be corrected in case something is wrong. I work harder if I feel like an idiot.

If you are confident that you want to do the preflight dance... below I describe as far as I got and.... failed with OPTIONS request being blocked.

Adding Maven Dependency

First of all you must check which version of Jetty you are using. According to that you can search for the corresponding Maven jetty-servlets Version. Once determined you can add the dependency to your pom.xml.

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlets</artifactId>
            <version>8.1.9.v20130131</version>
        </dependency>

Configuring web.xml

As described above declarations such as allowedMethods and allowedHeaders won't work by setting a "*". You have to tell explicitly what you want to allow.

Additionally I noticed (after some weeks of frustration....) that the order you add filters in web.xml seems to matter. The CORS filter has to be added before the springSecurityFilterChain filter. Otherwise authorization doesn't seem to work. I'm not sure here but I guess that the headers first have to be allowed by CORS.

    <!-- CORS related filter -->
    <filter>
        <filter-name>CORS</filter-name>
        <filter-class>
          org.eclipse.jetty.servlets.CrossOriginFilter
        </filter-class>

        <init-param>
            <param-name>allowedOrigins</param-name>
            <param-value>*</param-value>
        </init-param>
       <init-param>
            <param-name>allowedMethods</param-name>
            <param-value>GET,POST,DELETE,PUT,HEAD</param-value>
        </init-param>
        <init-param>
            <param-name>allowedHeaders</param-name>
            <param-value>
               origin, content-type, accept, authorization, 
                  x-requested-with
            </param-value>
        </init-param>
        <init-param>
            <param-name>supportsCredentials</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>CORS</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- Spring Security Filters -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>
            org.springframework.web.filter.DelegatingFilterProxy
        </filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

spring-security.xml

Finally create-session has to be set to stateless in the spring security configuration. Without enabling stateless authentication it can also lead to errors when executing a request from within Angularjs $http method.

<http use-expressions="true" create-session="stateless">
...
<http>

Test with Curl

You can test the headers with the following curl command below.

curl -v -X GET \
    -H "Origin: http://www.example.com" \
    -H "Authorization: Basic am9obkBqb2huLmNvbTpibGE=" \
    -H "Accept: application/json" \ 
    -H "Access-Control-Request-Headers: X-Requested-With" \  
    http://localhost:8080/api/user

The output should look similar to this.

* connected
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /api/user HTTP/1.1
> User-Agent: curl/7.27.0
> Host: localhost:8080
> Origin: http://www.example.com
> Authorization: Basic am9obkBqb2huLmNvbTpibGE=
> Accept: application/json
> Access-Control-Request-Headers: X-Requested-With
> 
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: http://www.example.com
< Access-Control-Allow-Credentials: true
< Access-Control-Expose-Headers: 
< Content-Type: application/json
< Transfer-Encoding: chunked
< Server: Jetty(8.1.9.v20130131)
< 
* Connection #0 to host localhost left intact
Here you should see the JSON DATA that is parsed back.
* Closing connection #0

Further resources

Saturday, April 13, 2013

Node.js Express JS and CORS (Cross Origin Resource Sharing)

Foreword

It seems that by default web browsers don't allow Cross Origin Resource Sharing which means that if a request is done from for example www.domain1.com to a resource on www.domain2.com it is treated as security issue. This is also the case if different ports are used with the same domain. So for example if your Angularjs application is running on localhost port 8000 and you are connecting on to an Express JS server that is running on localhost port 3000 it won't work. It's actually quite hard to debug as in Firefox the request will be displayed as red but there is no error message that is showing up explaining why the request is not working. Also the http status is 0 which is quite confusing. When however debugging the request with the Chrome browser there will be a message that says that XMLHttpRequests are forbidden.

One additional thing there is to say is that Chrome also does not accept such requests if the html file is opened directly in the browser. A web server will be required to execute the request (file:// is not working with all browsers, http:// is working).

More information on the issue can be found here.

Configuring Express JS

To solve this issue it is necessary to configure the Express JS server to explicitly allow such connections. To achieve this I have added following to the configuration of Express JS.
var express = require('express');

var app = express();

app.all('/*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
});

...
  • The first header setting is allowing access from different origins. "*" means that all origins will be accepted but it is also possible to set explicit origins.
  • The second header setting is necessary because Angular is adding a "X-Requested-With" XMLHttpRequest header when opening a connection to a resource.

Tuesday, April 9, 2013

Creating a simple webserver with node.js and Expressjs

Foreword

I played with angularjs for a while and struggled a little as I didn't find an easy way to simulate json responses. I want to decouple the client completely from the server so that it is possible to work in my nifty little javascript world without having to take care about the server part that is running on Spring/Java. I'm mainly doing that because I want to decouple as much code as possible to outsource parts to other developers that are experts in their segment. I don't want that a javascript developer needs knowledge about Java or any other development language. I also want to split projects in to chunks, spread them among different developers and set them together to the full picture once complete.
At last I found my solution with node.js and the Expressjs server. This is an easy example to setup a "one-script" solution to simulate json responses. This article is not intended to teach others but to share knowledge and learn.

Installation

Install node.js by downloading the corresponding binary package. I have downloaded the Linux binary package. I like to keep binaries like this in my home directory. So I did the following:
mkdir $HOME/Programs
cd $HOME/Downloads
tar -xvzf node-v0.10.3-linux-x64.tar.gz
mv node-v0.10.3-linux-x64 $HOME/Programs
Then I added the bin directory to the path so that the commands can be executed.
vim $HOME/.bashrc
export PATH=$PATH:$HOME/Programs/node-v0.10.3-linux-x64/bin
After opening a new terminal window I tested if node.js has been added to the path correctly:
node -v
v0.10.3

Creating the webserver

I have created a folder to install the webserver.
mkdir $HOME/Documents/node-server-example
Then I changed in to the directory and created a file called package.js.
cd $HOME/Documents/node-server-example/
vim package.json
{
  "name": "Express Test Server",
  "description": "Testing the Express Server",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "3.x"
  }
}
After that I have executed following command to install the Express Webserver.
npm install
This created a directory called node_modules with the express server dependencies in it. Then I have created a file called server.js that contains the server dependent code.
vim server.js
var express = require('express');

var app = express();

app.get('/api/user/email/testemail1', function(req, res) {
  res.status(201);
  res.json({ message: "this sends status header 201 (Created)" });
});
app.get('/api/user/email/testemail2', function(req, res) {
  res.status(200);
  res.json({ message: "this sends status header 200 (OK)" });
});

app.listen(3000);
console.log('Listening on port 3000...');
Then I started the webserver and browsed to the site with the Firefox RESTClient.
node server
Listening on port 3000...
And voila..... that was it. Pretty amazing.

Additional Sources

Sunday, March 10, 2013

Coding Tools

Foreword

It took me over a year coming from a PHP and ROR background to find the right Frameworks in Java. Learning a new language and a new Framework just takes it's time. Especially with Java. I was spoiled with extremely good documentation with PHP and especially ROR. With Java I have learnt that it can be very difficult to find documentation and especially examples. But now that I got used to it I wouldn't develop in any other language anymore...... apart from Javascript which is needed when wanting to develop modern decoupled web clients.

Hosting / Cloud Solution

I have been looking at different kind of Cloud solutions such as:
During comparing the prices I have discovered that prices especially for the Cloud based offerings can be very intransparent. Especially when looking at the AppEngine offering I discovered that if an application is not very streamlined to their environment or has small bugs there can be cost increases which could get painful if something goes wrong. That doesn't mean that it's bad and it can make sense for larger corporations that want to outsource the infrastructure management to save costs.

Since MongoDB that makes the life of database administrators quite easy however I have decided to go for Virtual Linux Servers with Rackspace or Amazon. My current environment is hosted on Rackspace, since I like the support they provide.

Development Environment

Editor: Intellij Idea

IntelliJ IDEA Community Edition is the open source version of IntelliJ IDEA, a premier IDE for Java, Groovy and other programming languages.
Website

Why Intellij Idea

  • Fast and reliable
  • Integrated Subversion
  • Spend time coding rather then to bug resolve and configure the IDE
  • Many plugins that actually work as intended

Web Framework environment

Development Language: Java

Java has an active community (also commercial community) and has been around for a long time. Many Enterprises like Banks, Insurance Companies and other Companies rely on it.
Website

Why Java

  • Well established in all kinds of businesses especially also large corporations
  • Scalable in different kind of ways
  • One of the most secure and long lasting development languages
  • Commercial Support available

Build Tool: Maven

Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information.
Website

Why Maven

  • License (Apache 2.0)
  • De-facto build tool for Java

Web Framework (Server Side): Spring (MVC)

Spring is the most popular application development framework for enterprise Java™. Millions of developers use Spring to create high performing, easily testable, reusable code without any lock-in.
Website

Why Spring

  • License (Apache 2.0)
  • Well known stable and robust framework
  • Used by many Enterprises
  • Adapters for most popular databases
  • J2EE compatible
  • REST Support 

Web Framework for Clients: Angularjs (Javascript)

HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web-applications. AngularJS lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop.
Website
  • License (MIT License)
  • Extends HTML rather then manipulating DOM
  • Relatively low learning curve
  • Makes use of dependency injection
  • Full featured client with support for i18n, templates and REST
  • Unit tests and e2e testing

Database: Mongodb

MongoDB (from "humongous") is a scalable, high-performance, open source NoSQL database. Written in C++, MongoDB features:
Website

Why MongoDB

  • Licensing (AGPL) Reference 1, Reference 2 The license can be used for free also for commercial projects.
  • Well documented
  • Low learning curve
  • Provides solution for general data and large data (GridFS) in a distributed environment
  • Supported by Spring
  • Includes large file support with GridFS

Resources

Java Application Server: Jetty

Jetty provides an HTTP server, HTTP client, and javax.servlet container. These components are open source and available for commercial use and distribution.
Website

Why Jetty

  • Dual Licensed (Apache, Eclipse)
  • Lightweight and fast
  • Used by Google and Yahoo for their Cloud solutions
  • Enterprise scalable