Archive for the ‘Spring’ Category

Specific environment setting with Spring

Friday, November 14th, 2008

There is one issue that people usually have with J2EE deployment. I call it specific environment setting. Imagine that you have several environments that you want to deploy your J2EE application to. For example development, test, stress test, staging or production. For all those environments you need specific settings like JDBC URL, JDBC user name and password, path to a directory for data export etc. The question is where to put such setting. If you store it in the WAR (JAR, EAR, SAR or other AR) you have to create specific archive for every environment.
It is not a big problem, provided you have an automated build. Nevertheless I do not like this solution. I like to have the same archive for all environments. This way I am sure that the application on production is exactly the same as the one I have tested on the test environment. Moreover, there is a problem with passwords. You have to make them part of the build process and effectively publish them by doing so.
One possible solution is to use JNDI. It is probably the best solution if you can use it. But what if you don't use big and heavy J2EE server. What if you use a servlet container like Tomcat or Jetty instead. In this case I have one of my favorite tricks for you. I use Spring configuration similar to the following one:

 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
	<property name="locations">
		<list>
			<value>
			  classpath:main-config.properties
			</value>
			<value>
			  file:///${user.home}/spring-test.properties
			</value>
		</list>
	</property>
	<property name="ignoreResourceNotFound" value="true"/>
	<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
 </bean>

<bean class="net.krecan.spring.TstBean">
	<property name="property1" value="${property1}"/>
	<property name="property2" value="${property2}"/>
	<property name="property3" value="${property3}"/>
</bean>

Spring tries to load a configuration file from user home directory. If the file is found, properties from the main-config file are overwritten by those found in the spring-test file. And you can even overwrite those by defining a system property with the same name.
I like it. This way every developer can have his own configuration. There is no danger of accidentally committing passwords to a source control system. You can use exactly the same WAR on every environment. It is relatively safe, although some system administrators do not like it. This way you can distribute an application over the internet without forcing users to unpack it, edit a config file and pack it again afterwards.

Závažná bezpečnostní chyba ve Springu odhalena!

Thursday, July 17th, 2008

Otázka: Je pravda, že v Košicích upálily rusa?
Odpověd rádia Jerevan: Ano, je to pravda, ale nebylo to v Košicích, ale v Kostnici a nebyl to rus, ale Hus.

Myslel jsem si, že jsem expert na senzační titulky. Ale tento je nepřekonatelný. Mohli jste na něj narazit dnes, například na theserverside.com. Na první pohled to vypadá, že našli závažnou bezpečnostní chybu ve Springu. Na druhý pohled člověk přijde na to, že Rádio Jerevan obnovilo vysílání.
Takže, je pravda, že je ve Springu bezpečnostní chyba? Ano je to pravda, jenom to není ve Springu, ale ve Spring MVC a není to chyba, ale vlastnost.
Jde o to, že Spring MVC napojuje (binduje) hodnoty v HTML formulářích na beany. Pokud mám ve formuláři políčko se jménem name a v beaně pole se stejným jménem, Spring MVC mi automaticky nastaví hodnotu v beaně podle hodnoty ve formuláři. A to je ta chyba. Může se totiž stát, že mám v beaně jinou sadu polí než v HTML formuláři. Útočník teoreticky může v dotazu poslat hodnotu pole, které nebylo ve formuláři, a které tudíž ani nečekám. Prostě a jednoduše mi pošle jeden parametr dotazu (request parameter) navíc. Pokud správně trefí jméno, Spring nastaví hodnotu pole beany, u kterého to neočekávám. Takže teoreticky může změnit něco, co nechci aby se měnilo. To je závažná věc, a je dobré ji mít na paměti. Rozhodně bych to nechtěl zlehčovat. Musím se přiznat, že mi to až dodnes nedošlo.
Nicméně pokud to trochu přeformuluji, tak z toho plyne, že nemáme věřit ničemu, co nám přichází od uživatele. To rozhodně není žádná novinka. Jenom na to často zapomínáme. Uvedený problém má ve Spring MVC jednoduché řešení. Prostě mu řekneme, jaká pole má napojovat.
Samozřejmě to není jenom problém Spring MVC, stejný problém budou mít všechny podobně fungující frameworky (možná kromě JSF). Když mi přijde HTTP dotaz, tak nevím, která políčka byla v HTML formuláři. On tam konec konců ani žádný HTML formulář být nemusel. Dotaz mohl být klidně vygenerovaný nějakou aplikací. Jediné co mohu udělat, je explicitně určit, která pole se mají nastavovat. To Spring MVC umožňuje, jenom to skoro nikdo nepoužívá.
Takže abych to shrnul. Ve Springu bezpečnostní chyba není (alespoň co je mi známo). Chyba ale může vzniknout při jeho neopatrném používání. Doufám že se zítra nedočtu, že je závažná chyba v Oraclu. Doslechl jsem se, že umožňuje zavolat DROP SCHEMA a to může mít závažné následky na integritu dat.

Spring field injection

Tuesday, June 17th, 2008

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.

(more...)