Rowell Belen

Musings of a Primal Brogrammer.

Latest Weekend Project - GitHub History Resume

One of the things I love about working for Pentaho is that I am almost never bored with the work. The development tasks are interesting and challenging – at least most of the time. I get to play with different technologies and architectures. Because I am satisfied with my professional work, I don’t feel the need to look for and work on “something cool” on the weekends. I am able to enjoy my weekends and spend time with my wife, family and friends, play sports, and EAT. =)


However, it’s been a long time since I worked on a personal weekend programming project so I decided to do something about it. Also, it’s been almost a year since I updated my blog so why not create a little project and post about it =)


The first thing that came to mind was to mess around with the GitHub API. I also have been wanting to play around with Node JS, Express JS and MongoDB. And it has been a few months since I worked on an Angular JS project, so I figure I should brush up on it.


So here’s what I came up with: A Personal GitHub Resume application. This app is consisted of 3 micro-applications deployed in Heroku

Java Background Application

  • Scheduled job that calls the GitHub REST API, grab the latest commits from every GitHub repository I have access to and store the information in a MongoDB database.

NodeJS/ExpressJS REST Server

  • Expose REST endpoints that query the MongoDB database for the list of Git commits and the diffs for each commit.

Angular JS Client

  • Display the list of commits in the browser and view and code changes for each commit.


You can preview the end product here: Personal GitHub Resume


Pentaho Kettle Web-Based Steps

Many of my colleagues here at Pentaho have expressed interest in a web technology based (HTML, JS, etc) PDI Step so I’ve been spiking on an experimental PDI plugin over the last few days. I’ve made some pretty good progress on it. For instance, I was able to embed a lightweight java web container to serve static web files and use Spring to “bridge” the web world and the Spoon world. This plugin does not depend on AgileBI nor the Pentaho Platform.


Some of the boilerplate integration and plumbing are already in place – like persisting the dialog settings to the StepMetaInterface. I am also able to run the transformation using the settings from the Web UI.


I was able to port the existing Generate Credit Card PDI Step to this new web-based UI. You can watch a short demo here:


If you would like to help with the project and contribute, you can find the GitHub repo here.

Please keep in mind that this is an experimental project. In a future post, I will discuss the architecture and some of the code I used to make this work.


Meet AngularJS!

This simple example demonstrates how to react on a model change to trigger some further actions. The value greeting will change whenever there’s a change to the name model.

Demo

JavaScript (helloAngular.js) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
require([
  'angular',
  'requirejs-domready'
],
  function (angular, domReady) {
    domReady(function() {

      angular.module('helloAngular',[]);
      angular.module('helloAngular').controller('Ctrl', function($scope) {
        $scope.name = "";
        $scope.greeting = "Greetings!"

        $scope.$watch("name", function(newValue, oldValue) {
          if (newValue.length > 0) {
            $scope.greeting = "Greetings " + newValue + "!";
          }
          else{
            $scope.greeting = "Greetings!"
          }
        });
      });

      angular.bootstrap($('#hello-angular'), ['helloAngular']);
    });
  }
);
HTML (helloAngular.html) download
1
2
3
4
5
6
<div id='hello-angular'>
  <div ng-controller="Ctrl">
    <input type="text" ng-model="name" placeholder="Enter your name">
    <h2 ng-bind="greeting"></h2>
  </div>
</div>

Simple Mediator Design Pattern for AngularJS

Code snippet for creating a simple mediator for cleanly separating concerns within an AngularJS application:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
angular
    .module('app', [])
    .controller('MainCtrl', function($scope, Order) {
      $scope.newOrder = function() { new Order(); }
    })
    .factory('$emit', function($rootScope) {
      return function() { $rootScope.$emit.apply($rootScope, arguments); }
    })
    .factory('Order', function($emit) {
      function Order() {
        this.email   = 'nobody@gmail.com';
        this.product = 'Macbook Pro';
        $emit('order:created', this);
      }
      return Order;
    })
    .factory('Email', function($window) {
      function Email(text) {
        $window.alert(text);
      }
      return Email;
    })
    .run(function($rootScope, Email) {
      $rootScope.$on('order:created', function(event, order) {
        new Email('Email sent to ' + order.email + ' for ' + order.product);
      });
    });

Another Custom Wicket Component - DateDropDownField

I needed a date drop down component (see below) for my current project. Unfortunately, I couldn’t find a built-in Wicket component that does the job. So why not write my own???

Date Drop Down

Java Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
public class DateDropDownField extends FormComponentPanel<Date>
{
  private static final long serialVersionUID = -839727513016106766L;

  private int month, day, year;
  private final DropDownChoice<Integer> monthField;
  private final DropDownChoice<Integer> dayField;
  private final DropDownChoice<Integer> yearField;

  public DateDropDownField(String id, IModel<Date> model)
  {
    super(id, model);

    // create month field
    monthField = new DropDownChoice<Integer>("month",
                   new PropertyModel<Integer>(this, "month"), // bind model
                   getMonths(),                               // list of choices
                   new MonthRenderer());                      // renderer
    monthField.setLabel(new Model<String>("month"));
    monthField.add(new RangeValidator<Integer>(0, 11));       // add a simple validator

    // create day field
    dayField = new DropDownChoice<Integer>("day",
                   new PropertyModel<Integer>(this, "day"), getDays());
    dayField.setLabel(new Model<String>("day"));

    // create year field
    yearField = new DropDownChoice<Integer>("year",
                   new PropertyModel<Integer>(this, "year"), getYears());
    yearField.setLabel(new Model<String>("year"));

    add(monthField);
    add(dayField);
    add(yearField);
  }

  @Override
  public void onBeforeRender()
  {
    // initialize model
    Date date = getModelObject();
    if(date == null)
    {
      date = new Date();
      setModelObject(date);
    }

    // synchronize main model and drop down components
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    month = cal.get(Calendar.MONTH);
    day = cal.get(Calendar.DAY_OF_MONTH);
    year = cal.get(Calendar.YEAR);

    super.onBeforeRender();
  }

  @Override
  public void convertInput()
  {
    try
    {
      // get values from individual components
      int month = monthField.getConvertedInput();
      int day = dayField.getConvertedInput();
      int year = yearField.getConvertedInput();

      // TODO check for valid date (example - 02/31/11 is invalid)

      // update the model from converted input
      Calendar calendar = Calendar.getInstance();
      calendar.set(Calendar.MONTH, month);
      calendar.set(Calendar.DAY_OF_MONTH, day);
      calendar.set(Calendar.YEAR, year);
      setConvertedInput(calendar.getTime());
    }
    catch(Exception e){
      setConvertedInput(null);
    }
  }

  // month choices
  private List<Integer> getMonths() {...}

  // day choices
  private List<Integer> getDays() {...}

  // year choices
  private List<Integer> getYears() {...}

  // render months as names instead of numbers
  private class MonthRenderer extends ChoiceRenderer<Integer>{
    private static final long serialVersionUID = -9037815586384085976L;
    @Override
    public String getDisplayValue(Integer object)
    {
      SimpleDateFormat format = new SimpleDateFormat("MMM");
      Calendar cal = Calendar.getInstance();
      cal.set(Calendar.MONTH, object);
      return format.format(cal.getTime());
    }
  }
}

HTML Code:

1
2
3
4
5
6
7
8
9
<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
  <body>
    <wicket:panel>
      <select wicket:id="month"></select>
      <select wicket:id="day"></select>
      <select wicket:id="year"></select>
    </wicket:panel>
  </body>
</html>

Again, Wicket saved the day. Here’s another reusable and self-contained component. To use this anywhere in your code, you simply need to add this new component to a form, panel, etc. No need to duplicate code or html markup!

Java Code:

1
add(new DateDropDownField("date", new Model<Date>(new Date())));

Extending Wicket’s AjaxFallbackDefaultDataTable

I was looking for a Wicket datatable component with sorting, paging and ajax support. Fortunately, I found this component.The only problem is, I want to be able to apply a different background style when selecting each row (hover) and execute some action when the entire row is clicked. These features are not supported out-of-the-box.


Wicket table


Luckily, Wicket makes it very easy to extend components. All I had to do was hook into the method that creates each row object and add the new behavior. Here’s the code…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class CustomAjaxFallbackDefaultDataTable<T> extends AjaxFallbackDefaultDataTable<T>
{
   // Constructor
   public CustomAjaxFallbackDefaultDataTable(String id,
                                             List<IColumn<T>> columns,
                                             ISortableDataProvider<T> dataProvider,
                                             int rowsPerPage)
   {
      super(id, columns, dataProvider, rowsPerPage);
   }

   @Override
   protected Item<T> newRowItem(String id, int index, final IModel<T> model)
   {
      // let super class create row item as usual
      final Item<T> item = super.newRowItem(id, index, model);

      // add style on mouse over
      item.add(new SimpleAttributeModifier("onmouseover",
                                           "this.style.backgroundColor='#80b6ed';"));

      // remove style on mouse out                                    
      item.add(new SimpleAttributeModifier("onmouseout",
                                           "this.style.backgroundColor='';"));

      // execute when row is clicked
      item.add(new AjaxEventBehavior("onclick"){
         protected void onEvent(AjaxRequestTarget target){
            executeOnClick(target, item.getModel());
         }
      });

      return item;
   }

   public void executeOnClick(final AjaxRequestTarget target, final IModel<T> rowItem)
   {
      String message = rowItem.getObject() + " was clicked";

      // execute server side code
      System.out.println(message);

      // execute client side code
      target.appendJavascript("alert('" + message + "');");
   }
}

Now the table looks something like this…

New Table


As you can see, I was able to extend a component with minimal effort. In addition, this component is reusable. The user can simply override the executeOnClick method if a different action is required when the row is clicked. Try that with JSF =)


Drupal / Java Integration

Drupal is one of the best open source content management systems currently available. One of Drupal’s strengths is its module development architecture. It allows developers to extend Drupal’s core features in a non-invasive and elegant manner. My only problem with Drupal is that it is written in …. PHP.


I am not a PHP expert, but I am an experienced Java Developer. I have written and deployed many Java enterprise applications in production. I am very familiar with a number of Java frameworks and technologies such as Spring, Struts, JSF, Wicket, JPA, JMS, Web Services, etc. I am also proficient on several Java development/testing tools. However, I do not know of any Java open source projects that can provide all of Drupal’s features out-of-the-box.


Luckily, I found a way to integrate Drupal/PHP and Java using the Quercus PHP engine. Because Quercus can run PHP scripts and expose Java methods in PHP, I was able to write Drupal modules by calling Java methods inside PHP functions. I can write most of the business logic in Java and only use PHP to write the Drupal “hooks”!.


I was also able to integrate other Java frameworks such as Spring, Vaadin and Wicket. I used SiteMesh to decorate the Wicket/Vaadin pages using the same Drupal theme.


Check out my POC web application here!

POC


Vaadin Demo - SuperImmediateTextField

Here’s another example of how easy it is to write Vaadin applications. I used an add-on component called SuperImmediateTextField. This component triggers an event each time the user enters a character in the text field.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Window mainWindow = new Window("Demo Application");
setMainWindow(mainWindow);

final LocationService service = new LocationService();
final Label cityAndStateLabel = new Label();
final SuperImmediateTextField zipcode = new SuperImmediateTextField();
zipcode.setInputPrompt("Enter zipcode");
zipcode.addListener(new KeyPressListener(){
  private static final long serialVersionUID = 2328719780185993498L;

  @Override
  public void keyPressed(KeyPressEvent event) {

    String cityAndState = null;
    String zip = (String)zipcode.getValue();
    if(StringUtils.isNotBlank(zip) && zip.length() == 5){
            cityAndState = service.getCityAndState(zip);
    }

    if(StringUtils.isBlank(cityAndState)){
            cityAndState = "Unknown";
    }

    cityAndStateLabel.setValue(cityAndState);
  }
});

HorizontalLayout layout = new HorizontalLayout();
layout.addComponent(zipcode);
layout.addComponent(cityAndStateLabel);

mainWindow.addComponent(layout);

EasyMock Objects Injection using Spring and Annotations

Declaring EasyMock objects as spring beans is easy…

1
2
3
<bean id="mailProcessor"  class="org.easymock.classextension.EasyMock" factory-method="createMock">
  <constructor-arg value="com.myservice.MailProcessor" />
</bean>

However, if the bean you want to test is dynamically proxied, you will get a ClassCastException. To work around this, you can create a custom annotation and bean post processor. This will allow you to annotate fields with @MockObject and Spring will provide the mock object using dependency injection…

Custom Annotation

1
2
3
4
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
public @interface MockObject {}

Custom Spring Bean Post Processor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@Component
public class MockObjectBeanPostProcessor implements BeanPostProcessor
{
  private Log logger = LogFactory.getLog(this.getClass());

  /* (non-Javadoc)
   * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
   */
  public Object postProcessBeforeInitialization(Object bean, String beanName)
    throws BeansException
  {
    // get all the fields
    Field[] fields = bean.getClass().getDeclaredFields();
    for(Field field : fields)
    {
      // check if field is annotated by Environment Property
      if(field.isAnnotationPresent(MockObject.class))
      {
        try
        {
          field.setAccessible(true);
          field.set(bean, EasyMock.createMock(field.getType()));
        } catch (Exception e) {
          logger.warn(e);
        }
      }
    }
    return bean;
  }


  /* (non-Javadoc)
   * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
   */
  public Object postProcessAfterInitialization(Object bean, String beanName)
    throws BeansException
  {
    // do nothing, return original bean
    return bean;
  }
}

Sample JUnit Test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/spring-test.xml"})
public class MailProcessorTest
{
  @MockObject private MailProcessor mailProcessor;

  @Test
  public void test()
  {
    // setup test behavior

    EasyMock.replay(mailProcessor);
  }
}

Declarative Caching using Spring

Java Class

1
2
3
4
5
6
7
8
9
10
package services.interfaces;

import org.springmodules.cache.annotations.Cacheable;
import services.model.Location;

public interface LocationService {

  @Cacheable(modelId="getLocationCacheModel")
  public Location getLocation(String zipcode);
}

ehcache.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
<ehcache>
  <defaultCache
    maxElementsInMemory="500"
    eternal="true"
    overflowToDisk="false"
    memoryStoreEvictionPolicy="LFU" />

<cache name="getLocationCache"
    maxElementsInMemory="50"
    eternal="true"
    overflowToDisk="false"
    memoryStoreEvictionPolicy="LFU" />
</ehcache>

Spring Configuration File

Add the following namespace definition: http://www.springmodules.org/schema/ehcache http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd

1
2
3
4
5
<ehcache:config configLocation="classpath:ehcache.xml" />
<ehcache:annotations>
  <ehcache:caching id="getLocationCacheModel"
          cacheName="getLocationCache" />
</ehcache:annotations>