peoples_scrum.pngAlmost a year ago, the company I work for, started an effort to adopt Scrum and Agile principles for software development. The company hired certified agile consultants, did extensive trainings and the whole department made a commitment to give Scrum our very  best. We were doing our version of "Scrum But" before that and I had small expectations from this new `experiment`. 

After a few months I couldn't not believe the difference. The scrum teams were more focused, people committed to the same goals, the quality of delivered software was better, distractions and impediments were reduced and work reclaimed its meaning and its creativity again. This continued for a while but in the next months fundamental changes brought in the surface a series of dysfunctions and issues. 

Over the course of six months the team changed 3 times. Some left, other changed roles, and a few joined us to form our current team. From the original 7 developers in the team when we started Scrum, now only 4 remain. We also changed scrum master 3 times. You would think this wouldn't affect us much but each of them worked differently and tried to apply a new way of doing certain things like retrospectives and the way we interact with our Scrum Board. This was confusing but experimenting with what works for you is important. Read More…

Recently at work we needed a way to log successful and failed hits to automatically disable web services for a failover system. There are many ways to implement this but for our application's needs and available tools, only two ideas made sense.

  1. MySQL: store these values on a memory table with delayed insertions.
  2. Memcached: implement Zend_Cache_Backend_Memcached ::increment function

I have seen the mysql solution working great for a couple thousands hits every minute but with our application hitting sometimes 10.000 web service calls every minute we became skeptical really fast. The memcached solution has two major problems: first it's memcaheD you don't know if the value you put in cache will actually make it back and secondly the Zend Memcached adapter needs a patch to implement the increment and a custom method to retrieve the counters. The reason increment has never been officially implemented before in ZF1 is because Zend stores values to cache in a custom way alongside the cache date and lifetime.

$result = @$this->_memcache->set($id, array($data, time(), $lifetime), $flag, $lifetime);

Memcached::increment needs the values to be numerical. I can only speculate why ZF1 dev team decided to save all values as array but anyway. I added the following two methods in Zend\Cache\Backend\Memcached.php

/**
 * Memcached::increment
 *
 * @param string $id cache id
 * @param numerical $offset to increase counter
 * @param numerical $initial value to set counter
 * @param int $extraLifetime
 * @return numerical new items value on success or FALSE on failure.
 */
public function increment($id, $offset = 1, $initial = 0, $specificLifetime = false)
{
	$result = $this->_memcache->increment($id, $offset);
	if (!$result) {
			$lifetime = $this->getLifetime($specificLifetime);
			$this->_memcache->add($id, $initial, false, $lifetime);
			$result = $this->_memcache->increment($id, $offset);
	}
	return $result;
}

/**
 * Custom get to retrieve incremental items
 *
 * @param string $id cache id
 * @return numerical|false cached item
 */
public function getCounterKey($id)
{
	$tmp = $this->_memcache->get($id);
	return is_numeric($tmp) ? $tmp : false;
}

The getCounterKey  is pretty straight forward, we wanted to bypass the default load method that tries to access the data from a custom array. The increment is a little more complex because we wanted a thread safe solution. The memcached::increment and memcached::add used like this, is thread safe.

Unfortunately you can't use these methods directly from the Zend_Cache_Core instance, you need a new patch for that to modify the Core class and all the adapters to add this new capability. It's doable but we were satisfied with just using the following snippet to access the Memcached adapter and the two new methods directly.

$cache = Zend_Registry::get('cache')->getBackend();
$cache->increment($key, 1, 0, 0);
$cache->getCounterKey($key);

The solution works like a charm when memcached is working properly but i would love someday to also test the MySQL idea. I would love to hear what solution other people used in similar problems.

Lithium's Model finders is a great way to avoid repeating the same code blocks over and over. If you google `Lithium finders` you will find many tutorials on this subject but most of the examples don't make much sense (at least to me) since they can be replaced by static methods inside a model class. I have set a simple rule on this matter: methods that don't apply to more than one model class, shouldn't become finders.

To take advantage of finders you must create your own Base model that other models will extend. Below you can see what i use with my two most used finders that i would actually love to see them become official...

class Model extends \lithium\data\Model {
	public static function __init() {
		static::finder('columns', function($self, $params, $chain) {
			$options = &$params['options'];
			$options['return'] = 'resource';
			if ($options['fields'] === null || empty($options['fields'])) {
				$options['fields'] = array($self::meta('key'));
			} elseif (count($options['fields']) > 1) {
				$options['fields'] = array_slice($options['fields'], 0, 1);
			}

			$result = array();
			foreach ($chain->next($self, $params, $chain) as $data) {
				$result[] = $data[0];
			}
			return $result;
		});

		static::finder('pairs', function($self, $params, $chain) {
			$options = &$params['options'];
			$options['return'] = 'resource';
			if ($options['fields'] === null || count($options['fields']) < 2) {
				$key = $self::meta('key');
				$title = $self::meta('title');
				$options['fields'] = array($key, $title);
			} elseif (count($options['fields']) > 2) {
				$options['fields'] = array_slice($options['fields'], 0, 2);
			}

			$result = array();
			foreach ($chain->next($self, $params, $chain) as $data) {
				$result[$data[0]] = $data[1];
			}
			return $result;
		});
	}
}
Read More…

NetBeans allows you to define either global or project specific code formatting options. To apply the following rules globaly navigate to Tools > Options > Editor > Formatting and select PHP language. To define project specific rules right click on your project and go to Properties > Formatting and check the `Use project specific options` and of course select PHP language.

Because the default rules of NetBeans 7.3 are really close to Lithium's coding standarts, we don't need to change many options. Let's begin...


netbeans_lithium_formatting.jpgTabs and Indents

  • Expand Tabs to Spaces: Uncheck
  • Number of Spaces per Indent: 4
  • Tab Size: 4
  • Right Margin: 120
  • Line Wrap: Off
  • Continuation Indentation: 0
  • Array Declaration Indentation: 4

Blank Lines

  • After Function: 0
  • After Open PHP Tag: 0
  • Before Close PHP Tag: 1
Read More…

grid2_slow_ai.jpg

I've be playing Grid 2 for some days now and i just completed the career mode. So i decided to enjoy my favorite car, Caterham SP/300R,  for a few last laps before i uninstall the game. The AI decided to reward me with some laughter. How AI Felix Wilson gets to be 3,399,011,919 minutes or 6,446 years slower than my time beats me!

In Java FX 2.x TableView is one of the controls you can't set a tooltip directly. You must set tooltips for TableCell or TableRow instead. The technique used in this turorial is very similar for both controls. Let's take a look!

Tooltips on TableCell

myTableColumn.setCellFactory(new Callback<TableColumn<DataModel, Object>, TableCell<DataModel, Object>>() {
	@Override
	public TableCell<DataModel, Object> call(TableColumn<DataModel, Object> p) {
		return new TableCell<DataModel, Object>() {
			@Override
			public void updateItem(Object t, boolean empty) {
				super.updateItem(t, empty);
				if (t == null) {
					setTooltip(null);
					setText(null);
				} else {
					Tooltip tooltip = new Tooltip();
					DataModel myModel = getTableView().getItems().get(getTableRow().getIndex());
					tooltip.setText(myModel.getTip());
					setTooltip(tooltip);
					setText(t.toString());
				}
			}
		};
	}
});

To add tooltips to column cells we have to set a custom cell factory for the target column. In our example DataModel is just the TableView's data model, change that to your model's name. Also this example's model returns Object so that's one more thing you will probably need to change over the casts. The getTip() method is there to also show you how to get the TableRow Data Item.

Tooltips on TableRow

myTable.setRowFactory(new Callback<TableView, TableRow>() {
	@Override
	public TableRow call(final TableView p) {
		return new TableRow() {
			@Override
			public void updateItem(DataModel item, boolean empty) {
				super.updateItem(item, empty);
				if (item == null) {
					setTooltip(null);
				} else {
					Tooltip tooltip = new Tooltip();
					tooltip.setText(getItem().getTip());
					setTooltip(tooltip);
				}
			}
		};
	}
});

Notice that for rows we need to set our custom row factory to the target table not column! Also it's much simpler to get the DataModel when working on rows, you only need to call getItem() method. 

Recently i started working on a JavaFX 2.x project and i needed a lot of TableViews for one of my stages. The most common and best practice to do this, is to implement a class that defines the data model and provides methods and fields to further work with the table. In my case defining 8++ Data Models seemed a little tedious so i started looking for a dynamic way to populate TableViews. I came accross this solution but that too seemed complicated. 

My solution is to create a generic Data Model which can by extended to add as many columns as you want, so not 100% dynamic then. The constructor works with a variant number of parameters so you don't have to create as many constructors as your fields, but you have to create as many getters as your fields. The second part, can be avoided but as long as you can auto generate them in any decent IDE there is no reason to go mad with reflections.

import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;

public class TableRow {

    private Object one;
    private Object two;
    private Object three;
    private Object four;
    private Object five;
    private Object six;

    public TableRow(Object... args) {
        Field[] fields = getClass().getDeclaredFields();
        int i = 0;
        for (Object arg : args) {
            try {
                fields[i++].set(this, arg);
            } catch (IllegalArgumentException | IllegalAccessException ex) {
                Logger.getLogger(TableRow.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    /**
     * @return the one
     */
    public Object getOne() {
        return one;
    }

    /**
     * @return the two
     */
    public Object getTwo() {
        return two;
    }

    /**
     * @return the three
     */
    public Object getThree() {
        return three;
    }

    /**
     * @return the four
     */
    public Object getFour() {
        return four;
    }

    /**
     * @return the five
     */
    public Object getFive() {
        return five;
    }

    /**
     * @return the six
     */
    public Object getSix() {
        return six;
    }
}

Then use the model just like in every other tutorial arround the web and the Oracled Docs. In my case it was something like this. Simple, generic and not overly complicated.

private TableView<TableRow> myTable;
@FXML
private TableColumn<TableRow, Object> myTableColumnOne;
@FXML
private TableColumn<TableRow, Object> myTableColumnTwo;

public void populateMyTable()
{
	myTableColumnOne.setCellValueFactory(new PropertyValueFactory<TableRow, Object>("one"));
	myTableColumnTwo.setCellValueFactory(new PropertyValueFactory<TableRow, Object>("two"));

	ObservableList data = FXCollections.observableArrayList();
	for(Map.Entry<String, Integer> entry: myHashMap.entrySet())
	{
		data.add(new TableRow(entry.getKey(), entry.getValue()));
	}
	myTable.getItems().setAll(data);
}

I hope, you will benefit from this solution, leave a comment if you have an idea on how to improve it even further.

javaFXTableViews.png

Edit: 4/25/20013
--------------------------------------------------

I took it on step further to remove the reflection in the constructor.


import java.util.ArrayList;
import java.util.Arrays;

/**
 * Generic data model is a wrapper for ArrayList to easily populate tableViews
 * and other javafx controls. This class would be perfect if java reflection
 * supported magic getters and setters like php or if there was a nice way to
 * dynamically add them during runtime.
 */
public class GenericModel {

    /**
     * The indexed list of objects
     */
    private ArrayList data;

    /**
     * Public constructor with variable number of parameters.
     *
     * @param args
     */
    public GenericModel(Object... args) {
        data = new ArrayList<>(Arrays.asList(args));
    }

    public Object get0() {
        return data.get(0);
    }

    public Object get1() {
        return data.get(1);
    }

    public Object get2() {
        return data.get(2);
    }

    public Object get3() {
        return data.get(3);
    }

    public Object get4() {
        return data.get(4);
    }

    public Object get5() {
        return data.get(5);
    }
}

Apparently komposta.net become famous today, who needs google analytics and webmaster tools when you wake up in the morning and u see that ~300 comments have been posted overnight (lol). Since September 2012 ~900 comments have been submitted. Only 14 of them are not spam, 4 of them are mine ;) and 300 were posted yesterday. A month ago i added a honeypot solution to the komposta comments system and it's working great but it's obvious some time limit catch has to be added to prevent this aggressive spam behavior. Some other fan factor they only target posts with popular keywords like twitter and zend.

spamAttack.png

Bots found me pretty fast because i set a redirection from my old site to komposta.net for about 2 months until t3-design.com domain expired. I kinda regret it now...

-----Edit: 12 hours later
It's still on, i wonder what will happen if i turn comments off for these 3-4 targeted posts... Next update tomorrow

spamAttack2.gif

-----Edit12 hours later
Turning commenting off for the targeted posts did the trick, i am gonna turn it back on to see if they gave up...

Lithium models are very flexible, schema can be lazy loaded by the first call to Model::schema(), unless it has been manually defined in the model subclass. Below there is an example of a model with predefined schema 

class UserGroups extends \lithium\data\Model
{
	protected $_schema = array(
		'id' => array('type' => 'id', 'length' => 10, 'null' => false, 'default' => null),
		'title' => array('type' => 'string', 'length' => 64, 'null' => false, 'default' => null),
		'description' => array('type' => 'string', 'length' => 255, 'null' => false, 'default' => null),
		'admin' => array('type' => 'integer', 'length' => 1, 'null' => false, 'default' => 0),
		'resources' => array('type' => 'string', 'length' => null, 'null' => false, 'default' => null),
	);

	protected $_meta = array(
		'key' => 'id',
		'locked' => true,
		'source' => 'user_groups'
	);
}

If you leave the schema configuration empty,lithium will retrieve the information directly from the data source. Which is nice until you understand that this extra step will be taken every time the model is initialized, which is a no no. That's why I am going to show you how to cache the model's schema. Firstly we need to set up a connection and the cache storage, here is some basic configuration:

use lithium\data\Connections;
use lithium\storage\Cache;

Cache::config(array(
	'default' => array(
		'adapter' => 'File',
		'strategies' => array('Serializer')))
);

Connections::add('default', array(
	'type' => 'database',
	'adapter' => 'MySql',
	'host' => 'localhost',
	'login' => 'root',
	'password' => '',
	'database' => 'database',
	'encoding' => 'UTF-8'
));

You probably have those two already in your application's bootstrap files, here is the piece of code that does the schema caching

Connections::get('default')->applyFilter('describe', function($self, $params, $chain) {
	if(!Environment::is('production')) {
		return $chain->next($self, $params, $chain);
	}

	$key = 'schema_' . md5(serialize($params['meta']));
	if(!$result = Cache::read('default', $key)) {
		$result = $chain->next($self, $params, $chain);
		Cache::write('default', $key, $result, '+1 month');
	}
	return $result;
});

By using Lithium's filters we can hook into the data source describe method to intercept default behavior. Firstly there is a check to skip caching if we are not in production environment. Then the system checks if schema has  already been in cache by using the model's meta as a unique key. If not, we allow the default procedure to run and we write the result to cache. 

Some notes
Recently Lithium's model and pretty much all data classes have been heavily updated, in many cases breaking backward compatibility. One of them is the model schema, when fully initialized is now an object instead of a simple arrray. The above snippet was written for the latest version in the dev branch but it will probably work for previous versions as well.

The best practice when writing a model is to manually define the schema. If you follow this principle I am not sure the above snippet will improve  much your app's performance. Initialize object vs retrieve object from cache. Maybe with a more advance cache adapter like APC???

Let me know how this worked for you!