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);
    }
}

banner-772x250.png

screenshot-1.pngSummy for wordpress generates excerpts for your posts by applying various algorithms for automatic summarization extraction. It scores your text's sentences, based on extended configuration options, and returns the highest ranked. WP-Summy is based on the Sum+my and was created in an attempt to further develop the Core Library through your feedback.

Important Notes

  • Currently only English & Greek languages are supported.
  • PHP 5.3 is required in order to use this plugin
  • It is tested to work for Wordpress 3.5 up to 3.8
  • Please report if it's compatible with older versions of wordpress

How To Use

  • Write your blog post as you normally do
  • Make sure excerpt and summy blocks are on screen
  • Experiment with all the options and hit Summarize

Installation

  1. Upload the entire folder `summy` to the `/wp-content/plugins/` directory
  2. Activate the plugin through the 'Plugins' menu in WordPress
Read More…

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...