Sunday, March 30, 2014

AngularJS - Select2 Infinite Scroll with Remote Data

I really like the select2 project, I've already used the library with the different configurations. I could not find however a good sample code for using it's infinite scroll option with AngularJS, so I made my own. Here's is my AngularJS version to the select2 docs Infinite Scroll with Remote Data code sample


Using a provider

The select2 collects it's data from an external API. API calls are made from a service, Obviously, calling this service from the Directive it self is a bad idea, that's why I used a provider for this purpose. The provider is accessed by the directive and returns a Promise while performing the service call. This way I keep my code components loosely coupled.

 $scope.movieListProvider = {  
    readData: function(term, page, pageSize) {  
     var deferred = $q.defer();  
     rtService.get({  
      q: term,  
      page_limit: pageSize,  
      page: page + 1  
     })  
      .$promise.then(function(data) {  
       deferred.resolve(data);  
      }, function(reason) {  
       deferred.reject(reason);  
      });  
     return deferred.promise;  
    }  
   };  

See The full code here



Sunday, March 23, 2014

Understanding Form Validation in AngularJS


For my current project I needed to add custom validation to form-input fields in AngularJS. In order to do that, I had to interact with the validation mechanism and to extend it. I started by looking in the AngularJS docs and resources I found on Google. You may gain some basic understanding by reading the resources that are out there, but like with most open-source technologies, to really understand what is going on you need to dive into the source code – in this case the entire Angular source is under angular.js file. Let us see how we can learn about the validation mechanism by understanding the Angular library source code.

Now, assuming your markup tells Angular the following:

 <input type="email" ng-model="user.email" />  

The result will be an input text field that is bound to a certain model property (represented by ng-model). Additionally, if you have bootstrap or any other CSS handling for this scenario the fields will react to the values that are typed inside it, typing anything but a valid email address will result in the field being marked on the screen as invalid.

But what is really happening under the hood? Let us look at the Angular code and see..

First, Angular maps each input tag to its input Directive, which means that when you are working under Angular and writing an “input” tag, your HTML will be compiled and replaced by an Angular directive.

 var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {  
  return {  
   restrict: 'E',  
   require: '?ngModel',  
   link: function(scope, element, attr, ctrl) {  
    if (ctrl) {  
     (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,  
                               $browser);  
    }  
   }  
  };  
 }];  

Note that the directive is expecting your input tag to include an ngModel, the created ngModelController is then passed to the link function. By doing this Angular creates a connection between the input field (the view) and the model. This connection is the core of every validation action.

Angular then uses the type attribute that was used ('email' in our case), to a matching function ('emailInputType' in our case), the code for emailInputType is as follows:


 function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {  
  textInputType(scope, element, attr, ctrl, $sniffer, $browser);  
  ....  
 }  

In the above code you can see the one of Angualr's internal basic code-reuse pattern. What this code does is referencing the “parent” function textInputType, this function is called from all text input types...from an OO point of view you can almost say that our emailInputType “extends” textInputType.

 function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {  
  textInputType(scope, element, attr, ctrl, $sniffer, $browser);  
  var emailValidator = function(value) {  
   if (ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value)) {  
    ctrl.$setValidity('email', true);  
    return value;  
   } else {  
    ctrl.$setValidity('email', false);  
    return undefined;  
   }  
  };  
  ctrl.$formatters.push(emailValidator);  
  ctrl.$parsers.push(emailValidator);  
 }  

As you can see, this code uses a simple REGEX validation test, it interacts with the ctrl (the ngModelController that was 'required' in the first snippet). Once a test succeeds or fails, the code updates the ngModelController's $setValidity method. This controller wraps the model used by the input, and the input tells it the model is now valid or invalid.

So what have we learned?

We have learned that:
  1. Angular renders your input HTML tags as directives,
  2. it uses REGEX to match the text inside the directive against the input type pattern (email in our case). 
  3. We have also learned how code reuse or extension like is done for Angular form items.







Tuesday, March 13, 2012

The Future of Flex? This Graph might give you a hint

Recently I've been meeting many Flex developers who are trying to figure out where's the Flex job market going, mostly asking themselves if it's time to switch to HTML5 or other client technologies. This graph might give you a hint. The graph displays the percentage of jobs found for each search terms on indeed.com. According to this graph, demand for Flex developers is obviously taking a huge fall while demand for HTML5 is rising in an amazing rate.

source: Indeed.com

I find two possible explanations to the graph, each one is also introducing a different forecast :
  • [Pessimistic] Flex is vanishing from the industry, in a couple of years it will no longer be used for new projects, Flex developers will still be able to find jobs maintaining existing projects, very much like developer of other technologies that have vanished form the job market.
  • [Optimistic] The market is over reacting to Adobe's recent Flex related strategy. Yes, some companies are avoiding the use of Flex for new projects and are exploring new technologies, but soon those companies will find out the obvious, HTML5\JS Are not mature enough and at this point can not offer companies a real alternative to Flex. Many of these companies will soon understand that leaving Flex was a mistake. They will get back to hiring Flex developers.

Which one of these forecasts is the right one? we'll just have to wait and see.

Tuesday, October 4, 2011

Tips for working with Spring Roo on STS


In my current project I do lots of use of Roo 1.2 under the SpringSource Tool Suite, Roo is becoming one of my favorite tools, especially after the recently added layering in version 1.2. Roo and it's support on the STS is still in it's early stages, there are a number of roo bugs that make the work process a little rigid. Here are a two tips which will help you get more from Roo on STS
  • Use the Navigator view on the tree, this way you'll be able to see the AJ code that roo generates and not only the Java classes. goto Window > Show View > Other > Navigator
  • When you start STS, make sure you open Roo shell so roo will update AJ files while you code. To do this right click the project on the tree > Spring Tools > Open Roo Shell

Monday, July 25, 2011

Looking back at Swing


I am currently using a Java third party library that uses Swing classes. I had to perform a simple task today, which included creating a Label with an Icon, using Swing's ImageIcon class. I looked into swing six years ago. Then, at the time I was the first Flex person in a Java developer’s team. The company I was working for was switching from Swing to Flex. It is interesting to look at Swing and learn how the concept of productivity in a GUI development environment has changed over such a short time period. For instance, this is how the Swing manual suggests that you create a label with an Icon:

ImageIcon icon = createImageIcon("images/middle.gif",
"a pretty but meaningless splat");
label1 = new JLabel("Image and Text", icon, JLabel.CENTER);
...
label3 = new JLabel(icon);

/** Returns an ImageIcon, or null if the path was invalid. */
protected ImageIcon createImageIcon(String path,
String description) {
java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
Can you imagine? All this code is required for a simple Label with an Icon! Software
development has changed in the last few years. Platforms and languages are expected to be more efficient and require less code and time from the developer.

Sunday, June 26, 2011

STS with Maven - java.lang.OutOfMemoryError: Java heap space


I've recently started using SpringSource Tool Suite (STS) for a large Flex on Java project, In the recent configuration I used eclipse to code and launched Maven using command line. STS provides a built in Maven launcher which really makes more sense to use (STS use m2eclipse to fully integrate maven with eclipse). The only problem is that once I tried to run mvn clean install I ran into the good old heap space issue:

java.lang.OutOfMemoryError: Java heap space
at java.io.BufferedWriter.(BufferedWriter.java:87)
at java.io.BufferedWriter.(BufferedWriter.java:70)
at java.io.PrintStream.init(PrintStream.java:83)
at java.io.PrintStream.(PrintStream.java:100)
at java.io.PrintStream.(PrintStream.java:62)
at org.aspectj.weaver.bcel.LazyClassGen.toLongString(LazyClassGen.java:764)
at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1837)
at org.aspectj.weaver.bcel.BcelWeaver.weaveWithoutDump(BcelWeaver.java:1755)
at org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify(BcelWeaver.java:1515)
at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1322)
at org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter.weaveQueuedEntries(AjPipeliningCompilerAdapter.java:435)
at org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter.queueForWeaving(AjPipeliningCompilerAdapter.java:371)
at org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter.afterProcessing(AjPipeliningCompilerAdapter.java:358)
at org.aspectj.ajdt.internal.compiler.CompilerAdapter.ajc$after$org_aspectj_ajdt_internal_compiler_CompilerAdapter$5$6b855184(CompilerAdapter.aj:98)
at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:652)
at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:392)
at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilation(AjBuildManager.java:1007)
at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performBuild(AjBuildManager.java:268)
at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:182)
at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:112)
at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
at org.aspectj.tools.ajc.Main.run(Main.java:355)
at org.aspectj.tools.ajc.Main.runMain(Main.java:234)
at org.codehaus.mojo.aspectj.AbstractAjcCompiler.execute(AbstractAjcCompiler.java:378)
at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:490)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:694)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:556)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:535)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:387)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:348)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:180)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:328)

The solution obviously is to increase the maximum heap size which is represented by the JVM -Xmx argument. Now there are a number of places you can find this argument (STS.ini is one of them) , but here's the one place I found that really makes the difference.

  • Goto the 'Run Configurations' popup of the current maven run you are trying to use (can be accesed by right clicking your project and selecting 'Run As')
  • Select your current run under 'Maven Build' in the tree
  • Select the the JVM tab and add your requested -Xmx settings (I chose -Xmx512m)
  • Press 'Apply' and 'Run'























You should now be able to run your Maven project.

Friday, April 1, 2011

Using relative url with RESTEasy path annotation

I ran into the following problem in the office this week, I'm working on a WAR project that exposes multiple services of different types (SOAP, REST, AMF). The REST part was written using Jboss's RESTEasy, after I renamed the REST servlet RESTEasy's services were no longer working. I was surprised to find out that the servlet name was hard coded into the code as part of the @Path annotation content, in order to update RESTEasy with the new servlet name, I was supposed to change the annotation content in a number of classes. Luckily there's a work around for this, and it's one that in my opinion you should always use, RESTEasy lets you specify the path prefix as a context variable, all you have to do is declare it in your web.xml in the following way...

in my code I have the following Path deceleration:
@Path("/rest-api/user")
rest-api is the servlet name, I'd like to make sure it's no longer hard coded in my application..

I will add the "mapping prefix" into my web.xml:
<web-app>
<servlet>
<servlet-name>rest-servlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>rest-servlet</servlet-name>
<url-pattern>/rest-api/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest-api</param-value>
</context-param>
.
.
.
</web-app>
Now when I've added the mapping prefix to the web.xml I can drop the servlet name from all path annotations:
@Path("/user")
In case I'de like to rename my servlet or for some reason change a part of the service URL, all I need to do is update the mapping prefix variable in the web.xml