Friday, December 28, 2012

Looking for JavaScript grid/table component

Recently I was looking for grid/table component in Javascript which is would be open-source, flexible enough and not tied heavily to some large framework. I'd like to share with you some brief notes of that research. I like SlickGrid more so I've explored it more.

SlickGrid

  • https://github.com/mleibman/SlickGrid/wiki
  • License: MIT
  • PROs:
    • Supports huge datasets via virtual scrolling. Looks like it's the only grid that supports horizontal virtual scrolling.  
    • Supports trees
    • Data provider API - allows model creation. Transparent update of model.
    • Long text editor support: double-clicick the cell and edit its content in a pop-up
    • Automatic shortening of long content
    • Supports cell horizontal spanning
    • Hosted on GitHub and actively accepts pull requests
  • CONs:
    • Poor documentation
    • No built-in dropdown editor
    • No fixed columns
    • Doesn't support cell vertical spanning.
    • Column width specified only in pixels - no percents. However, with grid.autosizeColumns() columns can be proportionally resized
    • Width adjusting is weird. Involves JavaScript handling, not just CSS.
    • Always displaying editor (for example, dropdown box) is not easy. It requires asyncPostRenderer
    • Mobile devices officially not supported (and not planned to support ever), but on my Android 4 tablet most functionality work OK. And there is a fork with support of mobile devices: https://github.com/reebalazs/SlickGrid-touch  

EditableGrid

jqGrid

  • http://www.trirand.com/blog/
  • License: MIT
  • PROs:
    • Rich feature set: trees, subtables etc
    • Mobile beta available
    • Supports column hierarchy, though API for this is a nightmare.
    • Hosted on GitHub, sometimes accept pull request
  • CONs:
    • No data model
    • Inconvinient configuration (for example, proprietary format for dropdown lists instead of using JS object)
    • Some plugins (for example, table to grid converter) pollute global namespace

DataTables

  • http://www.datatables.net/
  • License: GPLv2, BSD
  • PROs
    • Lightweight
  • CONs
    • Editability requires plugin
    • No data model
    • No tree support
    • Plugin for changing column width is buggy

Wednesday, December 19, 2012

Antipatterns: initialization after usage

I've seen such problem fiew times and I'm going to describe it as an antipattern - let's call it "initialization after usage". It could sound a bit like Captain Obvious, but isn't it typical for some pattern/antipattern catalogs? :)

The problem:

There is an object which has some fields initialized in one place, some in completely different place, and in the meantime the object is used somewhere. So when using the object it's not clear if its fields are completely initialized or not.

As an example - let's see Java object:

public class Person {
  private String firstName;
  private String lastName;
  private String postalIndex;
  private String city;
  public Person(String firstName, String lastName, String postalIndex) {
//apply values here
 }
//getters and setters go here
}
Its fields firstName, lastName and postalIndex are initialized immediately. The city is searched a lot later in some database by index and gets assigned later. In the meantime Person object can be displayed on some page, saved to DB etc., and during these operations nobody can be sure if city field is available or not.

Notice that problem doesn't apply to lazy-loaded or lazy-initialized fields as they can be retrieved on demand.
I'm also not talking about objects where some fields may not be applicable due to domain-specific concerns.
I'm talking just about fields that are set by some external systems that can't be controlled by the object itself and which always make sense from business point of view. Like in the example - if Person has a postalIndex then there's certainly some city assotiated with it (all right, could as well be village).

Possible solutions:

  1. Initialize all the fields immediately. However this may not be the option sometimes due to costly initialization of data which aren't used in all the cases.
  2. Factor out initialization to some utility method of another class. This is possible only if object contain enough information to build missing part, possibly with using external services.
  3. Move out fields to a wrapping class which maintains link to original object. Then in the second phase of initialization wrapped class instance would be created and used whereever additional fields needed. But this could be an overkill in some cases. A rather contrieved example could be like this (here it's definitely overkill, but it shows an approach):
  4. 
    public class PersonAddress {
      private Person person;
      private String city;
    //constructors, getters, setters go here
    }
    
  5. Modification of point 3 - subclass from original class

Tuesday, September 18, 2012

A good question for quiz about generics In Java

Suppose you have two classes:
public class Foo {
 private String[] array = (String[]) new Object[];

 public static void main() {
  Foo f = new Foo();
 }
}

public class Bar<T> {
 private T[] array = (T[]) new T[];

 public static void main() {
  Bar b = new Bar<String>();
 }
}
Will they compile? Will they run? At a first glance it may seem that both make inappropriate casting from superclass Object[] to subclass String[]. But if you look more carefully you may see that compiler replaces T[] with Object[], so class Bar compiles and runs without errors while Foo can't compile due to improper cast.

Friday, June 22, 2012

Quoting password for user in Oracle database

Recently I needed to create a user in Oracle11g database and I was surprised that for other people following expression works well:

CREATE USER name IDENTIFIED BY password
But I'm constantly getting ORA-00922: missing or invalid option error. Quoting the password solves the problem, so following expression works fine:

CREATE USER name IDENTIFIED BY "password"

It turned out that for password which contain only digits or start with a letter quotes aren't needed, so first expression works fine. But if the password starts with digit then quotes are required. So 123456, qwerty and asdf1234 don't need quotes, while "1234qwer" or "2asdf" should be quoted.

Wednesday, June 13, 2012

Collections.addAll performance

I was wondering how efficient addAll() method in Java collections is and looked through the JDK code (Sun/Oracle JDK 1.6.0-27). Here is code for ArrayList.addAll(...):


public boolean addAll(Collection<? extends E> c) {
 Object[] a = c.toArray();
        int numNew = a.length;
 ensureCapacity(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
 return numNew != 0;
}

So here you can see incomming collection content copied into intermediate array.
And here is code for ArrayList.toArray():


public Object[] toArray() {
 return Arrays.copyOf(elementData, size);
}

Pay attention that content of internal array is copied in order to return some value. And that's OK because internal array may contain empty cells in its tail. But what we have if we put it all together - if you make arrayList1.addAll(arrayList2) then content of arrayList2 is copied 2 times.

Well... honestly, I beleived before that standard data manipulation routines should be better optimized.

Friday, May 4, 2012

POST-Redirect-GET Pattern In Spring WebFlow



It's a good practice to redirect user to get requests after making some changes with post and this is
usually done by Spring WebFlow by default. But what if by some reason you need to use <webflow:always-redirect-on-pause value="false"/> option?
You can do this through java code. This approach is not described in WebFlow reference but documented via API javadoc.
Suppose you have some Action which is configured through WebFlow. If you want to make redirect to GET after this action you can modify action methods in following way:


public Event saveMyItem(RequestContext context) {
 //do some operations here

 //issue redirect
 context.getExternalContext().requestFlowExecutionRedirect(); 
 return success();
}

When WebFlow starts generating HTTP response it will send 302 code.


Friday, March 30, 2012

Beware of SchedulerFactoryBean

Recently I've discovered unpleasant side effect of org.springframework.scheduling.quartz.SchedulerFactoryBean which results to instable behaviour. It implements FactoryBean interface, so by default if you reference it in your context it returns Scheduler instance instead of the factory itself. But Scheduler instance creation is triggered by SchedulerFactoryBean.afterPropertiesSet(), and factory can't return Scheduler at all until it has been fully initialized.

See the point? Suppose we have some cyclic reference in the context and SchedulerFactoryBean relies on some other beans (for example, they may be needed for initial state configuration), and some of those other beans relies on scheduler in order to do some job later. Now if other beans happen to be created earlier then SchedulerFactoryBean (though, maybe not fully initialized) then everything works fine - half-ready beans are injected in SchedulerFactoryBean. But if scheduler factory gets created first then it tries to initialize another beans, which in they turn try to get Scheduler instance - and bang!!

org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'quartzScheduler': FactoryBean which is currently in creation returned null from getObject
This was in Spring 3.1

So, beware of this problem and avoid including SchedulerFactoryBean in cyclic references.