Archive for the ‘programowanie’ Category

package pl.bedkowski.code.userType.EnumSetUserType;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;

import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;

public class EnumSetUserType<E extends Enum<E>> implements UserType {
	private Class<? extends EnumSet> clazz = null;
	private Class<E> typeClazz = null;
	protected EnumSetUserType(Class<E> c) {
		this.clazz = EnumSet.noneOf(c).getClass();
		typeClazz = c;
	}

	private static final int[] SQL_TYPES = {Types.VARCHAR};
	public int[] sqlTypes() {
		return SQL_TYPES;
	}

	public Class returnedClass() {
		return clazz;
	}

	public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
		String name = resultSet.getString(names[0]);
		EnumSet<E> result = null;
		if (!resultSet.wasNull()) {
			String[] values = name.split(",");
			List<E> enumList = new ArrayList<E>();
			for(String value : values) {
				enumList.add(Enum.valueOf(typeClazz, value));
			}
			result = EnumSet.copyOf(enumList);
		}
		return result;
	}

	public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws HibernateException, SQLException {
		if (null == value) {
			preparedStatement.setNull(index, Types.VARCHAR);
		} else {
			Set<E> values = (Set<E>)value;
			String sqlValue = "";
			if (!values.isEmpty()) {
				StringBuffer buf = new StringBuffer();
				for(E val : values) {
					buf.append(val.name()).append(",");
				}
				sqlValue = buf.substring(0, buf.length() - 1);
			}
			preparedStatement.setString(index, sqlValue);
		}
	}

	public Object deepCopy(Object value) throws HibernateException{
		return value;
	}

	public boolean isMutable() {
		return false;
	}

	public Object assemble(Serializable cached, Object owner) throws HibernateException {
		return cached;
	}

	public Serializable disassemble(Object value) throws HibernateException {
		return (Serializable)value;
	}

	public Object replace(Object original, Object target, Object owner) throws HibernateException {
		return original;
	}
	public int hashCode(Object x) throws HibernateException {
		return x.hashCode();
	}
	public boolean equals(Object x, Object y) throws HibernateException {
		if (x == y)
			return true;
		if (null == x || null == y)
			return false;
		return x.equals(y);
	}
}

Usage

public class User {
    public enum TYPE{admin,guest};
}

///

import pl.bedkowski.code.userType.EnumSetUserType;

public class UserType extends EnumSetUserType<User.TYPE> {
	public UserType() {
		super(User.TYPE.class);
	}
}

Problem description

Another approach to the memoization topic mentioned previously came to me quite recently based on a problem with webservice call.

Imagine you have a webservice request/response exchange that’s taking a long time not only due to network latency but also due to the fact that your ws-logic performs a complicated ldap query.

So there are at least 3 reasons that might cause you a headache:

  1. slow internet connection
  2. slow ldap search
  3. big number of results that need to downloaded

In order to improve this situation results of method call might be cached inside ws-client’s code using ehacache. Cached entries will be identified based on method’s signature and passed arguments. The arguments should implement Serializable interface but this is already fulfilled since objects are passed through webservice calls.

Caching should be transparent to the caller – which should not know whether results he got were fetched from remote server or local cache. Additionally it should be configurable which methods calls should be cached or not and last but not least – since cached entries are identified by some key – it should be possible to define custom key-generator that would give the user freedom in defning key algorithm.

All the above requirements are summarized below:

  • webservice client api defined as interface
  • webservice client implementation that performs call to server
  • methods are chosen based on annotations
  • wraper defined as dynamic proxy so calls to client api are transparently may be cached and user is not aware if results come from cache or real call

Solution description

The solution will be spring-specific since Spring supports ehacache out-of-the-box.

Existing solutions

There exists already at least 3 solutions:

and somehow all of them combined fill the picture of what I’d expect from such a library:

Requirements
  1. Easy configuration with possibly as little xml as possible – smth like <context:component-scan> element with reasonable defaults
  2. Defining one annotation that enables method caching
  3. Including/Excluding methods from caching using annotation
Solution description

The approach descried in this post is realised by providing 3 main elements:

  1. Custom namespace handler implementing NamespaceHandlerSupport
  2. Custom bean definition parser extending AbstractSingleBeanDefinitionParser
  3. Custom BeanPostProcessor implmenting BeanFactoryAware interface
  4. Custom xsd

All points above respond to the requrements:

Points 1 and 2 let you declare usage of method cache with just one line of xml (after defining memoize namesapace) and creates EhCacheManagerFactoryBean and EhCacheFactoryBean behind-the-scenes freeing you from writing these explicitly inside you xml application context.

<memoize:use-method-cache
   config-location="classpath:ehcache.xml"
   cache-name="pl.bedkowski.code.memoize.sample.METHOD_CACHE" />

Point 3 finds classes annotated with Memoize annotation inside current context and wraps them inside Memoizer proxy, as well as fetches EhCacheFactoryBean instance created in the previous step.

@Component("wsClient")
@Memoize
public class WebServiceClientImpl implements WebServiceClient {

The Memoize annotation contains 2 properties:

  • keyGenerator – key generator class (must implement KeyGeneratorinterface)
  • type – one of Type.INCLUDE_ALL/Type.EXCLUDE_ALL

I think the last one needs some further explanation – it lets you define strategy for handling methods.

  • Default is Type.INCLUDE_ALL – which means that all methods that have non-void return type will be cached unless explicitly marked with Exclude annotation.
  • The reverse is Type.EXCLUDE_ALL which means that no method call will be cached unless marked with Includeannotation.

Sources, packages

Source available on github
Binaries available in repo

For one of my projects based on Zend Framework I do a lot of forms creation and validation but I found out is that there is no way to perform all validation on the client side, which is a huge time-saver.

So I figured that since all form generaing code is already in place and all elements are rendered so nicely – it should be possible to generate validation code with as simple step as just adding one line of decorator. Such a decorator would have to do the following steps:

  1. For each element defined in the form
  2. get defined validators
  3. for each validator generate validation javascript code
  4. get all error messages TRANSLATED if necessarry and apply them when validating (eg. using alert window)
  5. add onsubmit handler for running validation code

One major requirement is to have ONLY standard JavaScript code NO EXTERNAL libraries. Why? Because it just makes things easier. This doesn’t mean that it’s not possible – anyone interested can just extend JsValidation class and perform his own validation.

The idea isn’t new, there already exists an approach that performs javascript validation but it lacks translated error messages. Additionally it contains very bad line:

//Replace Form decorator with our own
$form->removeDecorator('Form');
$form->addDecorator(new CU_Form_Decorator_Form());

Why is it bad, you might ask – along JS decorator one is forced to use SPECIAL form decorator.

Currently my library supports 5 9 – in my opinion* – most widely used decorators :

There’s probably one thing that nees some more explanation – namely the strategy for keeping consistent order of running validation rules. So you do want to have check for non-empty before validating that value is float. In order to achieve it every validator is connected with corresponding STRENGTH integer value which defines the order of execution. So non-empty check is before float but less-than and greater-than might be executed in any order.

In the code it’s realized inside getValidator method whose second returned value is the execution order. Afterwards which value is used by „inner” class ElementValidators inside of its add method which uses it as an array key.

So this is it – the rest should be pretty straighforward – in case it isn’t feel free to leave some comments/questions below. One more remark – currently validation errors are displayed using alert function but yes I’m planning to display them inline the same way ZF’s validation erros are displayed. Erros are displayed the same way regular form validation happens so from user perspective there should be difference – additionally you can provide/override your own Zend.Form.ErrorReporter. Additionally validator rules are defines as functions in Zend.Validator.Rules namespace – each rules has the same name as its PHP counter-part, eg.

Zend.Form.Validator.Rules.Zend_Validate_StringLength = function(value, opts, msgs) {
}

Where:

  • value is the value to be validated
  • opts are options passed to the validator eg. minLength
  • msgs are internationalized messages displayed when validation fails

Source code available on github.

You can also checkout gists for this project

Usage:

<?php
error_reporting(E_ALL|E_STRICT);
set_include_path(get_include_path() . PATH_SEPARATOR .
                 './library');
require_once 'Zend/Loader.php';
  
Zend_Loader::registerAutoload();
//May need to have this set, the JavaScript file paths use baseUrl at the moment
//Zend_Controller_Front::getInstance()->setBaseUrl('public');
  

// display validation messages in French
$translator = new Zend_Translate(
    array(
        'adapter' => 'array',
        'content' => '/resources/languages',
        'locale' => 'fr',
        'scan' => Zend_Translate::LOCALE_DIRECTORY
    )
);
Zend_Validate_Abstract::setDefaultTranslator($translator);

$form = new Zend_Form();
$form->setView(new Zend_View());
$form->addDecorator(new Zend_Form_Decorator_JsValidation());
  
$name = $form->createElement('text', 'name', array(
        'label' => 'Name'
));
  
$name->addValidator('NotEmpty')
     ->setRequired(true);
  
$submit = $form->createElement('submit', 'ok', array(
        'ignore' => true,
        'label' => 'OK'
));
  
$form->setElements(array(
        $name,
        $submit
));

echo $form->getView()->headScript();
echo $form->getView()->inlineScript();
  
echo $form->render();
  


custom validator (php part):
<?php
class My_Form_Decorator_JsValidation extends Zend_Form_Decorator_JsValidation
{
const ORDER_MY_CUSTOM = 100;

    protected function handleCustomValidators($name, $msgs, $validator)
    {
     switch($name) {
     case 'MyCustomValidator':
     return array(
self::ORDER_MY_CUSTOM,
array(
'param' => $validator->getParam()
),
array(
'notValid' => $msgs[MyCustomValidator::NOT_VALID]
)
     );
     default:
     return parent::handleCustomValidators($name, $msgs, $validator);
     }

     return null;
    }
}

custom validator (javascript part):
(function() {
Zend = this.Zend || {};
Zend.Form = Zend.Form || {};
Zend.Form.Validator = Zend.Form.Validator || {};
Zend.Form.Validator.Rules = Zend.Form.Validator.Rules || {};

Zend.Form.Validator.Rules.MyCustomValidator = function(value, opts, msgs) {
if (value < opts.param) {
return msgs.notValid;
}
}

})();

* After one project with ZF

For my javascript project I was looking for an automated tool that would merge all my files into one, which then could be optimized by YUI compressor. I found combiner project developed by nzakas which used require-in-comment approach which was close to what I needed – my JS library uses require function for importing dependencies.

After forkeing it and started code analysis as well as other forks to see what changes would I need to make to adjust it to my needs and it looked like my improvement plan had the same points as most of the forks although I was planning to keep it as simple as possible, yet expandable.

So the plan was:

  • replace jargs with args4j
  • add generics to all collections
  • improve sorting and duplicates handling on the output collection by using TreeSet instead of List and proper Comparator
  • improve cyclic dependency management
  • improve files reading into SourceFile – remove todo List that was used for data exchange between processFile/processFiles methods
  • move file handling functionality into a subclass and thus enable fast exchange of the dependency algorithm – use it for css @import statement

First two points were no-brainers, so they went smoothly.

Sorting/duplicates removal

My biggest problem was the sorting algorithm (3rd point) – in the original version there was List with „manual” checks using List.contains function and after list has been filled with data it was sorted by using Collections.sort and appropriate Comparator.

This all worked fine but I was sure that the List could be replaced with TreeSet where both order and duplicates would be handled at once but original Comparator was a problem. It was good for sorting but not for insertion – when it found two non-related files with equal dependency size it returned 0 which in TreeSet terms meant that file would not be inserted  AT ALL. I checked TreeSet.add method and I found out that it uses binary search algorithm – so there are 2 cases to handle:

  • either there is no more elements, which meant element was inserted
  • Comparator returned 0, which meant that element was replaced.

And this was it – I just had to make sure that elements with the same number of dependencies are handled consistently until there is no more elements or the same element is found. This meant comparing 2 non-related element with the same number of depedencies by name.

Get rid of todo property

Second thing was processSourceFiles method that used extra list in order to exchange dependencies found by processSourceFile method. This looked weird from the beginning, so I was wondering if adding a return value to processSourceFile would help. Afterwards I noticed that processSourceFiles can be called recursively and thus letting go todo list.

Simplify cyclic dependency management

Than there was cyclic dependency handling – there used to be an extra loop that would check all files one-by-one if any of them is not already dependent on currently processed one. So I figured that it would be much easier to do the check inside addDependency which meant getting rid of all overloaded methods and leaving just one that accepts SourceFile object. Finally addDependency method checks if current object is already a dependency of added object (passed as parameter) and if it is, it returns false.

Subclass for reading files

So than removing file reading algorithm and adding Css handler was really easy because dependency reading was already fleshed out, so baiscally I just had to move it outside FileComparator class.

Ostatnio zaciekawił mnie fragment kodu korzystający z metody getGenericSuperClass, gdyż do tej pory cały czas byłem przekonany, że nie ma możliwości pobrania informacji o generycznym typie przekazanym w szablonie, ale okazało się, że nie jest to całkiem zgodne z prawdą – taka możliwość istnieje i już jakiś czas temu pisał o niej Neal Gafter na swoim blogu w poście zatytułowanym Super Type Tokens. Po jakiś czasie dodając ich ograniczenia.

Jak już pisałem – byłem kompletnie zaskoczony i myślałem, że to tylko dyskusja w akademickim stylu, ale szybko okazało, się że mogę go wykorzystać w moim kodzie testowym :)

Mój proces pisania testu jednostkowego zazwyczaj zaczyna się od stworzenia klasy poprzez wizarda eclipse’owego, wybrania metod do testowania i otwarciu wygenerowanej klasy. Później dopisuję obiekt podlegający testowi jako własność, która jest odtwarzana w metodzie oznaczonej adnotacją Before i tak w kółko.

Przykładowy kod mógłby wyglądać tak:

public class MyObject {
   public void func(){}
}

public class MyObjectTest {

   private MyObject obj;

   @Before
   public void init() throws Exception {
      obj = new MyObject();
   }

   @Test
   public void testFunc() {
   }
}

I dzisiaj uznałem, że chyba można napisać do tego jakoś automat, czyli generyczną klasę zawierającą jako parametr obiekt, który ma być testowany i dodatkowo metodę „odtwarzającą” go przed każdym testem:

import java.lang.reflect.ParameterizedType;

public abstract class MyBaseClass<T> {
   protected T tObj;
   private Class<T> clz;
   protected MyBaseClass() {
     clz = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
   }

   @Before
   public void ____init() throws Exception {
      tObj = clz.newInstance();
   }
}

No i przykładowy test:

public class MyObjectTest extends MyBaseClass<MyObject> {
   // inicjalizacje zalatwia klasa nadrzedna
   @Test
   public void testFunc() {
   }
}

Ostatnio w projekcie powstała potrzeba odrzucenia części wyników asocjacji przed wysłaniem obiektu „w świat” :)

Zaczniemy od przeglądu możliwych rozwiązań:

  • najprostsze, które przychodzi do głowy to pobranie asocjacji get’erem, przejechanie się po wynikach i wybranie „właściwych”
  • można użyć złączenia, jednak problem pojawia się w przypadku OUTER JOIN’ów, bo Hibernate pobiera wszystkie elementy a dodanie warunku w wherze powoduje potraktowanie OUTER’a jak INNER’a i w przypadku braku wyników dostaniemy pusty zbiór wyników
  • można skorzystać z Hibernate’a 3.5, który dostał dodatkowy parametr do metody createCriteria, która to właśnie jest dodatkowym kryterium filtrującym dane
  • niestety dla tych „pechowców”, takich jak ja, którzy muszą używać starszych wersji jest też nadzieja :)

I na tym ostatnim elemencie będę się dzisiaj skupiał – otóż jak, poradzić sobie z tym problemem w elegancki sposób (bez konieczności zgłębiania wewnętrznych mechanizmów). Są to wspomniane już adnotacje @FiterDef/@Filter, a do opisu ich działania posłużę się przykładem prostego mapowania  dwóch klas – rodzica i dzieci, w relacji jeden-do-wielu, korzystając z adnotacji @OneToMany/@ManyToOne.

Zaczniemy od stworzenia klasy rodzica:


@Entity
@Table(name = "mock_object")
public class MockObject implements Serializable {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id", updatable = false, nullable = false)
	public Long getId() {
		return id;
	}

	@OneToMany(mappedBy = "mockObject", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
        public Set<MockSubObject> getSubObjects() {
		return subObjects;
	}
}

Ze względu na czytelność listing zawiera tylko niezbędne elementy – czyli encję MockObject, która odpowiada tabeli w bazie mock_object i zawiera pole id a także set sub objectów, którego definicja jest poniżej:

@Entity
@Table(name = "mock_sub_object")
public class MockSubObject implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", updatable = false, nullable = false)
    public Long getId() {
	return id;
    }

    @Column(name="name", length=50)
    public String getName() {
	return name;
    }

    @ManyToOne(fetch = FetchType.EAGER)
    public MockObject getMockObject() {
	return mockObject;
    }

Żeby nie było tak całkiem nudno, dorzuciłem jeszcze jakąś nazwę :)

No i spróbujmy napisać do tego left join’a:


Criteria crit = session.prepareCriteria(MockObject.class)
   .createCriteria("subObjects", "su", Criteria.LEFT_JOIN)
   .add(Restrictions.eq("su.id", 1L);

List<MockObject> mo = crit.list();

Zapytanie sprecyzowane w ten sposób spowoduje, że zbiór wyników będzie pusty nawet mimo tego, że tabela mock_object nie jest pusta.

Można temu zaradzić w następujących krokach:

  1. Dodając definicję filtra do encji MockObject.
  2. Deklarując warunek dla kolekcji subObjects
  3. Włączając filtr i wstawiając parametr przed wywołaniem zapytania.
  4. Dodając DISTINCT_ROOT_ENTITY_TRANSFORMER

Do dzieła:


// definicja filtra

@FilterDef(name = "findByName", parameters = { @ParamDef(name = "name", type = "string") })
public class MockObject implements Serializable {

Jak widać filtr przyjmuje jeden parametr o nazwie name i typie string.

Teraz właściwy warunek:


@Filter(name = "findByName", condition = "(name = :name)")
 public Set<MockSubObject> getSubObjects() {

I reszta podczas tworzenia zapytania – które wraz z włączonym filtrem umożliwia filtrowanie danych po atrybucie name:

        Criteria crit = session.createCriteria(MockObject.class)
        	.add(Restrictions.eq("id", 1L))
        	.addOrder(Order.asc("id"));

        session.enableFilter("findByName").setParameter("name", "name1");

        crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

        List<MockObject> lMo = list(crit);

Dla pewności można sprawdzić jeszcze wygenerowane zapytanie:

-- Hibernate:
select this_.id as id0_1_, this_.version as version0_1_, subobjects2_.mockObject_id as mockObject3_3_, subobjects2_.id as id3_, subobjects2_.id as id1_0_, subobjects2_.mockObject_id as mockObject3_1_0_, subobjects2_.name as name1_0_ from mock_object this_ left outer join mock_sub_object subobjects2_ on this_.id=subobjects2_.mockObject_id and (subobjects2_.name = ?) where this_.id=? order by this_.id asc

Wygląda na to, że dodatkowy warunek został uwzględniony :)

Źródła standardowo na gicie.

Dodałem do repozytorium druga wersje skryptu sticky buttons, poprawki zawierają:

  • poprawione zachowanie w przypadku przewijania kontenera
  • dodanie rekurencyjnego wyliczania animacji po zjechaniu z guzika
  • animacja po zjechaniu jest tylko „odtwarzana”, klatka po klatce, co powinno przyspieszyć jej przetwarzanie
  • poprawione zachowanie w przypadku złapania guzika
  • poprawione zachowanie w przypadku przejechania po liście guzików (problem z płynnością animacji)

Do tego cała masa zmian w kodzie – można powiedzieć, że skrypt jest napisany od zera. Zawiera ujednolicony system obsługi układu współrzędnych poprzez klasę Point, która zwiera metody manipulujące współrzędnymi x,y odpowiednio. Ona także unifikuje jquery’owe left/right oraz pageX/pageY z eventa.

Dopisałem także funkcyjkę bind służącą wiązaniu parametrów funkcji do późniejszego wykorzystania. W przypadku zakończenia animacji, wysyłane jest zdarzenie, którego obsługa powoduje wygaszenie wątku animacyjnego jak również wykrycia zmiany położenia elementu w przypadku np. scroll’owania zewnętrznego kontenera i zakutalizowania swojej pozycji.

Ostatnio podczas pracy nad jednym projektem w wielu miejscach w kodzie należało przepisać przychodzące żadanie z jednego transfer object’a na drugiego (powody tegoż przepisywania są dla tego artykułu zupełnie nieistotne) w związku z czym w wielu miejscach w kodzie pojawiły się elementy do siebie łudząco podobne:

target.setSomeProperty(source.getSomeProperty())

Co oczywiście nasunęło mi myśl czy nie dałoby się tego jakoś wydzielić, ale ograniczała mnie myśl, że java to przecież nie taki dajmy na to JavaScript w którym takie figle to chleb powszedni.

Rozwiązanie podsunął mi dopiero Tomek swoim artykułem nt. BeanUtils – wystarczy przecież pobrać własności z jednego beana za pomocą metody describe i następnie korzystając z metody populate je zaaplikować – no i niby wszystko cacy, ale jest parę niuansów które mi przeszkadzają:

  • całe api jest statyczne…
  • dodawanie Converter‘ów jakioś tak topornie wygląda
  • nie ma możliwości definiowania własności, która zmieniła nazwę pomiędzy Beana’mi
  • i jak śię jakaś własność nie przepisze, to nie dowiemy się o tym dopóki nie będziemy jej próbowali pobrać, czyli znaaacznie za późno

Stąd pomysł na klasę BeanTransformer, która powinna umożliwiać:

  • definiowanie własności ze zmienioną nazwą
  • definiowanie własności do pominięcia
  • definiowanie Coverter’a z wykorzystaniem generycznego interfejsu, który sam będzie przenosił informację o typie dla jakiego ma być aplikowany
  • sprzątanie konwerterów po zakończonej konwersji

I tak właśnie narodziła się klasa BeanConverter, którą omówię poprzez opis jej metod i klas wewnętrznych upraszczających całą zabawę :)

No to zacznijmy od początku – zadeklarujmy klasę:


public class BeanTransformer {

}

Przydałaby się metoda pozwalająca definiować własności, które nie bedą nam potrzebne i przechowująca je w Set‘cie:

	private Set<String> skipProperites = new HashSet<String>();
	public BeanTransformer skip(String firstProperty, String... propertyNames) {
		skipProperites.add(firstProperty);
		if (propertyNames != null) {
			skipProperites.addAll(Arrays.asList(propertyNames));
		}
		return this;
	}

Jak widać przy okazji umożliwia chain’y i dodawanie więcej niż jednej własności za jednym zamachem.

Następnie potrzebujemy metodę pozwalającą zdefiniować własności, których nazwa się zmieniła:

	private Map<String, String> renameProperties = new HashMap<String, String>();
	public BeanTransformer rename(String fromProperty, String toProperty) {
		renameProperties.put(fromProperty, toProperty);
		return this;
	}

I teraz wystarczy przejechać się po własnościach, sprawdzić które na które przechodza, usunąć zbędne i sprawdzić czy coś zostało i ew. zgłosić błąd.

	private Set<String> filterCorrectProperties(final Map<String, Object> properties) {
		// first remove properties that should be skipped
		properties.keySet().removeAll(skipProperites);

		// than go over the rest of them
		Set<String> foundProperties = Sets.filter(renameProperties.keySet(),
				new Predicate<String>() {
					public boolean apply(String fromProperty) {
						if (properties.containsKey(fromProperty)) {
							Object v = properties.remove(fromProperty);
							String newKey = renameProperties.get(fromProperty);
							properties.put(newKey, v);
							return false;
						}
						return true;
					}
				});

		return foundProperties;
	}

Teraz gdy już mamy listę przefiltrowanych własności możemy je przepisać do docelowego beana

	@SuppressWarnings("unchecked")
	public <F, T> T transform(F fromBean, T toBean) throws NotUsedPropertiesException {
		try {
			Map<String, Object> properties = (Map<String, Object>) PropertyUtils.describe(fromBean);

			Set<String> foundProperties = filterCorrectProperties(properties);

			if (!foundProperties.isEmpty()) {
				throw new NotUsedPropertiesException(foundProperties);
			}

			BeanUtils.populate(toBean, properties);

			return toBean;
		} catch (IllegalAccessException e) {
			throw new NotUsedPropertiesException(e);
		} catch (InvocationTargetException e) {
			throw new NotUsedPropertiesException(e);
		} catch (NoSuchMethodException e) {
			throw new NotUsedPropertiesException(e);
		}
	}

Zakładamy, że reszta własności przepisuje się 1-1.

Jeszcze miłą opcją byłaby możliwość dodania własnego converter’a dla typów innych niż standardowe – tutaj skorzystam również z klasy szablonowej, która będzie rozszerzać interfejs Converter, ale dodatkowo definicja zawiera typ klasy który dany konwerter obsługuje, co daje nam 2 zalety:

  • Klasa niesie cały zasób informacji nt. konwersji
  • Część wspólnej logiki może być wydzielona na zewnątrz

Zacznijmy od samego interfejsu, który będzie prosty do bólu:

	public static interface Converter<T> extends org.apache.commons.beanutils.Converter {}

Teraz metoda rejestrująca takiego konwerterka nie musi mieć explicite podanej klasy, pobierze ją sobie z szablonu korzystając z metody getGenericInterfaces:

	public <T> BeanTransformer addConverter(Converter<T> c, boolean skipConverterImpl) {
		Type[] types = c.getClass().getGenericInterfaces();
		Class<T> clz = (Class<T>) ((ParameterizedType) types[0]).getActualTypeArguments()[0];
		if (!skipConverterImpl) {
			c = new ConverterImpl(clz, c);
		}
		converters.put(clz, c);
		return this;
	}

Jeszcze tylko pozostaje wyjaśnić znaczenie tajemniczej klasy ConverterImp – ona to mianowicie jest sposobem na wydzielenie części wspólnej funkcjonalności dla wszystkich converter’ów a jednocześnie nie wymusza na użytkowniku jej znajomości, wiec po prostu dekoruje metodę convert i dopiero dopuszcza do głosu konkretna implementację, jeżeli wspólna implementacja nie wie jak dany obiekt utworzyć, no ale dośc gadania:

	private static class ConverterImpl<T> implements Converter<T> {
		private Class<T> self;
		private Converter<T> target;
		public ConverterImpl(Class<T> self, Converter<T> target) {
			this.self = self;
			this.target = target;
		}
		@SuppressWarnings("unchecked")
		public Object convert(Class arg0, Object arg1) {
/*
			corrected after comment by bob
			if (self.isAssignableFrom(arg1.getClass())) {
*/
			if (self.isInstance(arg1)) {
				return arg1;
			}
			return target.convert(arg0, arg1);
		}
	}

Mając convertery możemy je sobie włączać i wyłączac przed i po konwersji:

	private void registerConverters() {
		for (Class<?> clz : converters.keySet()) {
			ConvertUtils.register(converters.get(clz), clz);
		}
	}

	private void deregisterConverters() {
		for (Class<?> clz : converters.keySet()) {
			ConvertUtils.deregister(clz);
		}
	}

// w metodzie transform dodajemy wywołania:
			registerConverters();
			BeanUtils.populate(toBean, properties);
			deregisterConverters();

Dla tych, których zaciekawiłem tym wpisem wrzuciłem projekt (wraz z unitami!) na githuba.

Klasa Joiner dostępna w pakiecie google-collections oszczędza programiście nieznośnego sprawdzania pierwszego, bądź ostatniego elementu kolekcji/tablicy w celu sprawdzenia czy wymagane jest dodanie separatora, co znacznie poprawia czytelność kodu.

Jednak podczas korzystania z tej klasy natrafiłem na drobny problem – podczas łączenia elementów przy pomocy metody join kolejne kawałki są dodawane poprzez wywołanie metody toString na obecnie przetwarzanym elemencie (chyba że jest to CharSequence lub jego pochodne). W moim przypadku elementem kolekcji był javaBean i chciałem zamiast wywołania metody toString zawołać sobie jego metodę getId, no i niestety jedyna radę jaką znalazłem w dokumentacji, było przekształcenie kolekcji beanów w kolekcje typów prostych (lub ich zawijaczy) a następnie uruchomienie na tejże kolekcji Joiner’a, mniej więcej tak:


// [ctrl] + [shift] + O

interface MyBean {

public Integer getId();

}
		// [ctrl] + [shift] + O

		List<MyBean> myBeans = new ArrayList<MyBean>();

		// w kolekcji cośtam przyszło skądś indziej

		// teraz zamieniamy ją na kolecję Integerów
		List<Integer> ids = Lists.transform(myBeans, new Function<MyBean, Integer>() {
			public Integer apply(MyBean b) {
				return b.getId();
			}
		});

		Joiner commaSeparated = Joiner.on(",");
		String commaSeparatedIds = commaSeparated.join(ids);

No i wszystko ładnie i pięknie, ale dlaczego nie mogę sobie od razu wywołać metody join przekazując jej jako pierwszy parametr funkcji konwertującej mojego beana na string. No to do dzieła – będziemy potrzebowali tak naprawdę 3 metody: appendTo, join, no to po kolei:

	public final <T> String join(Function<T, String> f, Iterable<T> parts) {
		return appendTo(f, new StringBuilder(), parts).toString();
	}
	public final <T> StringBuilder appendTo(Function<T, String> f, StringBuilder builder, Iterable<T> parts) {
		try {
			appendTo(f, (Appendable) builder, parts);
		} catch (IOException impossible) {
			throw new AssertionError(impossible);
		}
		return builder;
	}

I ostatnia

	public <A extends Appendable, T> A appendTo(Function<T, String> f, A appendable, Iterable<T> parts) throws IOException {
		checkNotNull(appendable);
		Iterator<T> iterator = parts.iterator();
		if (iterator.hasNext()) {
			appendable.append(f.apply(iterator.next()));
			while (iterator.hasNext()) {
				appendable.append(separator);
				appendable.append(f.apply(iterator.next()));
			}
		}
		return appendable;
	}

Teraz jedyne co trzeba zrobić to przekazać funkcję jako pierwszy parametr:

		// [ctrl] + [shift] + O

		List<MyBean> myBeans = new ArrayList<MyBean>();

		// w kolekcji cośtam przyszło skądś indziej

		Joiner commaSeparated = Joiner.on(",");
		String commaSeparatedIds = commaSeparated.join(new Function<MyBean, String>() {
			public String apply(MyBean b) {
				return ""+b.getId();
			}
		}, myBeans);

Pozostaje tylko mały zgrzyt – konstruktor Joiner’a został zadeklarowany jako prywatny, więc niestety nie da się po tej klasie podziedziczyć – pozostaje copy-paste :(

Ostatnio zdażyło mi się trafić na dosyć intrygujący problem: testy junitowe odpalane były poprzez runner’a spring’owego co umożliwiało wstrzykiwanie zależności poprzez config testowy. No ale to wszyscy znamy – problem pojawił w momencie gdy chciałem dodać runner’a mockito’wego gdyż adnotacja @RunWith nie oferuje takiej możliwości, no i już byłem przekonany, że trzeba będzie zakasać rękawy i napisać jakieś api np. z użyciem dekoratora, ale jak zwykle wyszedł ze mnie leń i postanowiłem sprawdzić czy ktoś już tego czasem nie zrobił.

Okazało się, że nie, ale ze względu na to, że @RunWith została dodana nieco późno i nie była do końca przemyślana. W junit’cie 4.7 wprowadzono tzw. Intereceptors ale zmieniono ich nazwę wraz z  wersją 4.8 na Rule.

Co daje nam ta adnotacja – możemy ją zaaplikować do publicznej własności naszego testu, i musi on implementować interfejs MethodRule. Reszta to już bułeczka z masełkiem – MethodRule zwraca Statement‘a, który w działaniu przypomina nieco advice’a Around, znanego użytkownikom AOP – zawijamy sobie statement, wywołujemy co nam trzeba, następnie execute na oryginale i już. Dla przykładu stwórzmy taka klase, która pozwoli nam tworzyć mocki, mockitowe z wykorzystaniem adnotacji @Mock.

package pl.bedkowski.code.rules;

import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.mockito.MockitoAnnotations;

public class InitMocks implements MethodRule {

	public Statement apply(final Statement stmt, FrameworkMethod arg1, final Object arg2) {
		return new Statement(){
			@Override
			public void evaluate() throws Throwable {
				MockitoAnnotations.initMocks(arg2);
				stmt.evaluate();
			}};
	}

}

No i jakis przykladowy tescik:

package pl.bedkowski.code.rules;

import static org.mockito.Mockito.when;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.mockito.Mock;

interface SomeInterface{
	String doSmth();
}

public class SampleTest {

	@Rule
	public MethodRule i = new InitMocks();

	@Mock
	private SomeInterface my;

	@Test
	public void testing() throws Exception {
		when(my.doSmth()).thenReturn("33");
	}
}