Spring field injection

Few weeks ago, I worked on an interesting task. I had to find out how to migrate my customer’s proprietary framework to Spring. The framework was quite similar to Spring, although there were some differences. They used combination of XML and annotation configuration. Every property had special annotation saying that it is a property. XML schema for configuration was generated based on this annotation. So basically you had XML configuration that said what to inject to the annotated fields. The problem was that they did not have set methods for the fields.

And of course, the customer did not want to change all their classes just to migrate to Spring. It meant that they needed configure all the beans using Spring, but inject the dependencies directly, not through set methods.

I know that it is ugly and not recommended but in this case I think I have good excuse. It is a customer’s requirement. The question of course is how to do it.

You can try to use Spring post-processor. If you register instance of InstantiationAwareBeanPostProcessor you can use method postProcessPropertyValues to manipulate with property values just before Spring attempts to inject them. So you can inject the values into fields by yourself. And it works. The trouble is that you have to do property instantiation and conversion by yourself too. I almost managed to do it when I encountered a big problem – inner beans. In Spring, you can define a bean inside another bean. In order to inject the inner bean to the outer bean, the inner bean has to be already instantiated. But postProcessPropertyValues method is called before inner bean instantiation. So that is a blind alley.

OK, post-processor can not be used, let’s do it more hard-core. Spring has something called BeanWrapper. It is used by Spring for setting bean properties. Great, that is the point where I can force Spring to inject into the fields. The only thing I need to do, is to inject my BeanWrapper implementation into Spring. There is only one small trouble. It is not possible to do it. Unsurprisingly, dependency injection does not work inside the dependency injection code. I tried hard, but did not find any simple and safe way how to replace default BeanWrapper implementation. (If you know how to do it, please let me know)

So, if it is not possible to force Spring to inject without set method, let’s give him what he is asking for. The final solution is simple. When instantiating beans, I do not instantiate the original class but a subclass that is generated in the runtime and has all needed set methods. For the class generation I use Javassist, it is simple and powerful. To make the integration with Spring as simple as possible, I use factory bean. So the Spring XML config file looks like this

	<bean id="beanFactory" class="net.krecan.beanfactory.SetMethodGeneratingBeanFactory"/>
	<bean id="sampleClass" 
		      factory-bean="beanFactory"
		      factory-method="createBean">
		<constructor-arg value="net.krecan.beanfactory.Sample"/>
		<property name="textProperty" value="test.txt"/>
		<property name="intProperty" value="123"/>
		<property name="simpleSample">
			<bean factory-bean="beanFactory" 
			   factory-method="createBean">
				<constructor-arg value="net.krecan.beanfactory.SimpleSample"/>
				<property name="textProperty" value="hallo"/>


			</bean>

		</property>
	</bean>

Instead of providing class name in the bean definition, factory-bean attribute is used. Spring than calls method createBean on the factory bean with parameter taken from the constructor-arg element. It contains the class name of the bean. The result of the method call is used as a bean instance and all the properties are set by Spring.

Of course, you do not have to write it this way every time you want to instantiate this kind of bean. Simple custom namespace can be created in order to simplify the syntax.

In the future, when my customer realize that setters are a good thing, the factory can be easily replaced by a dummy implementation.

To reiterate, direct injection of dependencies from XML to the fields without using set methods is not supported by Spring. You can choose between XML based configuration using set methods or annotation based configuration. It is extremely hard to change default Spring behavior. And maybe it is a good thing. So if you need to do ugly XML based field injection, your only choice is to generate set methods in the runtime. Or maybe something else, but I have no idea what.

Continue reading

Joel o software

V porovnání s řízením týmu lidí jsou C++ šablony triviální.

Dneska budu psát o něčem co asi všichni znáte. O sérii Joel on Software, kterou jsem měl příležitost přečíst si v knižní podobě.

A začnu rovnou chválou. Je to nejlepší knížka, kterou jsem o psaní programů kdy četl. Joel nejen že tomu rozumí, on umí navíc i psát. A to vtipně. Takže se střídají okamžiky, kdy se člověk směje s okamžiky kdy si říká „Tak takhle to je“.

Kniha je rozdělena do několika základních částí. Joel v ní probírá témata týkající se programování, managementu, strategie a ekonomie softwarových projektů. Zakončuje částí o .NETu, která je docela zajímavá i pro Javistu. Mě obvykle přestávají podobné knihy po polovině bavit. Připadá mi, že se autor už jen opakuje. U této knihy tomu tak nebylo. Takže jsem ochoten mu odpustit i to, že je prašivý Microsofťák.

Knize uděluji deset hvězdiček z deseti a vyhlašuji ji jako povinnou literaturu. Až vás příště potkám, tak si vás jen tak zběžně přezkouším. Běda tomu kdo ji nebude umět nazpaměť. Ale vážně, pokud pro vás programování není jenom dočasný způsob obživy, přečtěte si to. Když už ne knižně, tak alespoň online. Většina textů je ke stažení na internetu.

No a nebyl bych to já, kdybych se nedopustil neodpustitelného porušení autorských práv neautorizovanou citací Joelova testu, kterým si můžete zjistit, jak na tom je vaše firma

  1. Používáte source control?
  2. Jste schopni udělat build v jednom kroku?
  3. Děláte denní build?
  4. Máte databázi chyb?
  5. Opravujete chyby před tím než píšete nový kód?
  6. Máte aktualizovaný plán?
  7. Máte specifikaci?
  8. Mají programátoři tiché pracoviště?
  9. Používáte nejlepší nástroje, které se dají koupit?
  10. Máte testery?
  11. Píší uchazeči o zaměstnání kód během pohovoru?
  12. Děláte testy použitelnosti za pomocí lidí odchycených na chodbě?

Za každou kladnou odpověď si přičtěte bod. Joel tvrdí, že většina organizací se pohybuje kolem tří bodů. Ale neradujte se, že máte pět bodů. Výsledek 10 a nižší je prý také špatný. Ale abych vás potěšil, v knize se dočtete i to, jak to můžete právě vy napravit.

Sníme v kódu

Software is hard. [Donald Knuth]

Tak jsem tu zas s další pidirecenzí knihy pro úchyly jako jsem já a doufám že i vy. V originále se jmenuje Dreaming in Code, a napsal ji Scott Rosenberg. Její podtitul mluví za vše: „Dva tucty programátorů, tři roky, 4 732 chyb a jedna výprava za výjimečným programem.“
O čem, že to je? Pan Mitchell Kapor, zakladatel Lotusu, si vydělal nějakých sto milionů dolarů na Lotusu 1-2-3. No a jelikož nevěděl co s penězi, tak se rozhodl, že založí Open Source projekt, který vyřeší jeho a ostatně i naše trable s MS Outlookem. Že napíše něco mnohem lepšího. Program, který změní svět. Který úplně převrátí náš pohled na na PIM programy. Převratný programu Chandler. Že jste o něm nikdy neslyšeli? Není divu. Ono se to moc nepodařilo. O to je ta kniha zajímavější.
Autor po tři roky sledoval marnou snahu týmu, tento program napsat. A musím přiznat, že je to čtení jen pro silné nátury. Je to čtení o tom, jak se neustále dohadovali, co vlastně chtějí naprogramovat, jak to chtějí naprogramovat, co to bude dělat, jak to bude vypadat, jaké knihovny použít. V prvním roce v podstatě nenapsali nic užitečného. K první použitelné verzi se blížili asi po třech letech! To už to ovšem autor knihy vzdal a šel dělat něco užitečnějšího. Podobně otřesný zážitek jsem zažil naposled, když jsem sledoval Sin City ve Francouzštině.
Co knihu dělá stravitelnou a i užitečnou jsou citace a četné odkazy na další literaturu. Autor často odbočí, problémy Chendleru zobecňuje a píše, co o problému kdo zajímavého napsal. Takže, až vás příště budu ohromovat nějakým citátem, tak víte, kde jsem ho našel.
Takže abych to shrnul, pokud vás zajímá vývoj software, máte silný žaludek a nemáte dost odstrašujících příkladů z vlastní praxe, kniha Dreaming in Code je pro vás ta pravá. Dávám jí chabých 6 hvězdiček z deseti. A dovolte mi zakončit citátem, který knihu docela vystihuje. Jde o odpověď, kterou dal Linus Torvalds na otázku, jakou radu by dal lidem, kteří se pouštějí do velkého projektu.

Nikdo by se neměl pouštět do velkých projektů. Začněte s malým, triviálním projektem a nikdy neočekávejte, že bude velký. Když to budete čekat, jenom ho předimenzujete a budete si myslet, že je důležitější, než pravděpodobně v dané fázi je. Nebo ještě hůř, představa té hromady práce vás může úplně odradit. Takže začněte v malém a myslete na detaily. Nemyslete na velký obraz a fantastický design. Pokud to neřeší okamžitou potřebu, je to zcela jistě předimenzováno.