Archive for the ‘java’ Category

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

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

W pewnym projekcie, miałem mały problem związany z przejrzystością kodu – mianowicie w kodzie przewijały się różnego rodzaju strategie przechodzenia po elementach:

  • kolekcje (java.util.Collection) – for-each
  • enumeracja (java.util.Enumeration) – for z licznikiem i metoda hasMore elements
  • listy node’ów (org.w3c.dom.NodeList) – for z licznikiem i metoda getLength wyznaczająca koniec

Dodatkowym problemem zaciemniającym kod w przypadku ostatniego elementu jest fakt, że metoda NodeList.item zwraca ZAWSZE node’a, nawet jeżeli użytkownik WIE, że wszystkie node’y będą typu Element i tak musi je sobie zrzutować.

Rozwiązaniem problemu było dodanie metody szablonowej, która na wejsciu przyjmie obiekt, po ktorym będzie sobie chodzić iterator i będzie go zwracać, no to do dzieła:

package pl.bedkowski.util;

import java.util.Enumeration;
import java.util.Iterator;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class IterGenerator {

	public static <T> Iterable<T> iter(final Enumeration<T> e) {
		return new Iterable<T>() {

			public Iterator<T> iterator() {
				return new Iterator<T>() {

					public boolean hasNext() {
						return e.hasMoreElements();
					}

					public T next() {
						return e.nextElement();
					}

					public void remove() {
						throw new UnsupportedOperationException();
					}

				};
			}
		};

	}
}

Tutaj jak widać sprawa była prosta – interfejs Enumeration jest szablonem, więc zamiana jednego na drugi odbyła się w miarę bezboleśnie. Z NodeListą już nie pójdzie tak łatwo, no ale do dzieła :)

	public static <T extends Node> Iterable<T> iter(final NodeList e, Class<T> clazz) {
		final int size = e.getLength();
		return new Iterable<T>() {

			public Iterator<T> iterator() {
				return new Iterator<T>() {

					private int current = 0;

					public boolean hasNext() {
						return current < size;
					}

					@SuppressWarnings("unchecked")
					public T next() {
						return (T) e.item(current++);
					}

					public void remove() {
						throw new UnsupportedOperationException();
					}
				};
			}
		};
	}

Jak widać w tym przypadku już nie jest tak pięknie, potrzeba dodać adnotację, żeby ukryć warninga, ale przynajmniej użytkownik nie musi sobie tym zaprzątać głowy. Dodajmy jeszcze małe ułatwienie:

	public static Iterable<Node> iter(final NodeList e) {
		return iter(e, Node.class);
	}

I teraz tylko jakiś przykładzik:


import static pl.bedkowski.util.IterGenerator.iter;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class Example {
	public static void main(String[] args) {
		NodeList list = null; // wiem, wiem NPE, ale nie mam zadnej list pod reka
		for(int i=0;i<list.getLength();i++) {
			Node n = list.item(i);
			System.out.println(n.getLocalName());
		}

		// teraz wykorzsytamny nasz iter
		for(Node n : iter(list)) {
			System.out.println(n.getLocalName());
		}

		//teraz gdy wiemy, ze lista zawiera same obiekty typu Element
		for(int i=0;i<list.getLength();i++) {
			Element e = (Element) list.item(i);
			System.out.println(e.getTagName());
		}

		// z wykorzytaniem itera
		// teraz wykorzsytamny nasz iter
		for(Element n : iter(list, Element.class)) {
			System.out.println(n.getTagName());
		}
	}

}

Jak widać pracy wcale nie trzeba włożyć dużo a korzyść spora :)

Dzisiaj chciałbym przybliżyć nieco problem z jakim się ostatnio spotkałem i proste rozwiązanie za pomocą wzorca delegacji a konkretnie jego implementacji w postaci cglib’owej klasy MethodDelegate.

Problem pojawił się w wyniku dodawania adaptera dla grupy niepowiązanych obiektów z biblioteki zewnętrznej, które oferowały bardzo zbliżone zestawy interfejsów. Na potrzeby tego wpisu załóżmy, że klasy są 2 i obie oferują metody getName oraz getValue.


public class Klasa1 {

private String name,value;

public String getName(){return name;}

public String getValue(){return value;}

}

public class Klasa2 {

private String name,value,type;

public String getName(){return name;}

public String getValue(){return value;}

public String getType(){return type;}

}

Pierwsze rozwiązanie problemu polegało na opakowaniu danej instancji w momencie wywołania danej metody sprawdzeniu czy obiekt jest odpowiedniego typu, przy użyciu operatora instanceof, zrzutowaniu na odpowiedni typ i wywołaniu danej metody na tymże typie. Implementacja może wyglądać tak:


public class Wrapper {

private Object wrapped;

public Wrapper(Object wrapped){this.wrapped = wrapped;}

public String getName(){

if( wrapped instanceof Klasa1 ){

return ((Klasa1)wrapped).getName();

}

else if( wrapped instanceof Klasa2) {

return ((Klasa2)wrapped).getName();

}

}
// to samo dla getValue()
}

Rozwiązanie działa jednak utrzymanie takiego kodu (szczególnie w przypadku większej ilości klas) jest dość męczące.

Drugim podejściem jest skorzystanie z reflection api i pobranie metody z obiektu bez sprawdzania typu:


public class Wrapper {

// ctor bez zmian

public String getName() {

Method m = wrapped.getClass().getMethod("getName", (Class[])null);

return m.invoke(wrapped, (Object[])null);

// pominalem obsluge fury wyjatkow

}

}

Rozwiązanie już nieco mniej męczące, jednak jego wadą jest brak informacji o typie a i wywołanie metody poprzez „invoke”, które nie należy do najprzyjemniejszych.

Rozwiązanie trzecie to skorzystanie z cglib’owej klasy MethodDelegate. Polega ono na pobraniu danej metody przy pomocy deklaracji interfejsu i wywolanie korzystając z niego właśnie, no ale do rzeczy:

public class Wrapper {

public interface GetName(){public String getName();}

public String getName() {

GetName o = (GetName)MethodDelegate.create(wrapped, "getName", GetName.class);

return o.getName();

}

}

Moim zdaniem najlepsze rozwiązanie  z całej trójki, gdyż zapewnia zwarty kod, metoda wywoływana to także getName, co znacznie zwiększa czytelność a dodawanie kolejnych nie wymaga podobnie jak w przypadku reflection api, żadnych nakładów.

Ostatnio zastanawiałem czy da się wykorzystać parser javy, w celu kompilacji klasy w locie i utworzenie obiektu z byte kodu bez zapisu na dysk. Zacząłem szukać trochę po necie i okazało się, że w javie 6 jest całe api poświęcone kompilacji w locie – wszystko w pakiecie javax.tools.

Łącząc oba linki poniżej można napisać elegancki kod, któremu wystarczy podać nazwę klasy i string do skompilowania a na wyjściu dostaniemy piękny obiekt, oczywiście zakładając, że mamy jakis interfejs, możemy skorzystać z parametryzacji typu wyjściowego, wszystko w linkach poniżej:

- Kompilacja Stringa z zapisem na dysk

- kompilacja w locie z wykrzytaniem api eclipse