Vášnivý programátor

Zrovna procházím seznam doporučené literatury z jOpenSpacu. Dostal jsem se tedy i ke knize Passionate Programmer, kterou napsal Chad Fowler. Nebojte se, nejde o růžovou knihovnu, to jsem jen neodolal pokušení při překladu. Vhodnější by asi bylo použít slovo náruživý.

Kniha má podtitul, který přesně vyjadřuje její obsah: „vytváříme pozoruhodnou kariéru ve vývoji software“. Je prostě o tom, jak dělat práci, která člověka baví a jak v tom být dobrý. Jde o druhé, upravené vydání, první se jmenovalo „My Job Went to India: 52 Ways to Save Your Job“. V druhém vydání se změnil nejenom název, kniha prý byla předělána aby kladla důraz právě na tu „pozoruhodnost“ vaší kariéry.

Jde o takový mix ne příliš navazujících kapitol, které se dívají na práci vývojáře z různých stran. Dočtete se, jak se stát špičkovými programátory, jak o tom dát vědět nadřízeným, jak se neustále zlepšovat, jak si vybrat zaměření a jak se stát slavným. Krása, škoda že už slavný jsem.

Ani moc nevím co bych víc napsal, je potřeba si tu knížku přečíst. Pokud obsah knihy shrnu, tak bychom si měli správně vybrat obor, stát se v něm nejlepší, dát to všem vědět a zajímavá kariéra nás nemine. Zní to sice samozřejmě, ale snadné to není. V knížce se právě dočtete dost triků a tipů jak toho všeho dosáhnout. Doporučuji.

Spring WS Security on both client and server

Recently, I have been playing with Spring WS with WS-Security. I just want to write down how it works. Do not except anything special, just simple example of basic security operations.

The example

We want to implement both client and server side. The client will sign the message, encrypt some part of it and add a timestamp. To make it more complex and real-life like we will sign the message using private key with alias “client” and encrypt the message using public key called “server”. Server will validate that the request is valid and will just sign the response using his key called “server”. Please note that I have picked Wss4j implementation because the configuration seemed to be easier than Xws.

Client

It’s easy to do configure client interceptor like this.

<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
	<property name="interceptors">
		<list>
			<ref local="wsClientSecurityInterceptor"/>
		</list>
	</property>
	...
</bean>

<bean id="wsClientSecurityInterceptor"
	class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
	<property name="securementActions" value="Timestamp Signature Encrypt" />
	<!-- Key alias for signature -->
	<property name="securementUsername" value="client" />
	<property name="securementPassword" value="" />
	<property name="securementSignatureCrypto" ref="clientCrypto"/>
	<property name="securementEncryptionCrypto" ref="clientCrypto"/>
	<property name="securementEncryptionParts" value="{Content}{http://javacrumbs.net/calc}a"/>
	<!-- Key alias for encryption -->
	<property name="securementEncryptionUser" value="server"/>
	
	<!-- Validation config -->
	<property name="validationActions" value="Signature" />
	<property name="validationSignatureCrypto" ref="clientCrypto"/>
</bean>

<bean id="clientCrypto" class="org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean">
    <property name="keyStorePassword" value="mypasswd"/>
    <property name="keyStoreLocation" value="classpath:security/client-keystore.jks"/>
</bean>

As you can see, there is nothing special. We just define which actions to take and properties. The only confusing part is, that key alias is defined as “securementUsername”.

Whit this configuration we will get following SOAP message.

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
	xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
	<SOAP-ENV:Header>
		<wsse:Security
			xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
			SOAP-ENV:mustUnderstand="1">
			<xenc:EncryptedKey Id="EncKeyId-F5114C147B958E706212759086159355"
				xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
				<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
				<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
					<wsse:SecurityTokenReference
						xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
						<ds:X509Data>
							<ds:X509IssuerSerial>
								<ds:X509IssuerName>CN=Test Server,OU=Test</ds:X509IssuerName>
								<ds:X509SerialNumber>1275904530</ds:X509SerialNumber>
							</ds:X509IssuerSerial>
						</ds:X509Data>
					</wsse:SecurityTokenReference>
				</ds:KeyInfo>
				<xenc:CipherData>
					<xenc:CipherValue>fwFM7ShJ1xd7dTGrkh0410sTmW92OPB1q1fpzB21XFIe36siDDJWGgbw5B94yjmGK2YaPOWLb7cpVTYPzc9VUDs7Jc42CtrhT2H6eZ7CDiA60Ugz+qi2UyyfMDK6Vrdj9J68rij5P12AiBeTnd2wlhI29+71XbUpD5weHDHjMtQ=
					</xenc:CipherValue>
				</xenc:CipherData>
				<xenc:ReferenceList>
					<xenc:DataReference URI="#EncDataId-4" />
				</xenc:ReferenceList>
			</xenc:EncryptedKey>
			<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
				Id="Signature-2">
				<ds:SignedInfo>
					<ds:CanonicalizationMethod
						Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
					<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
					<ds:Reference URI="#id-3">
						<ds:Transforms>
							<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
						</ds:Transforms>
						<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
						<ds:DigestValue>AU9utUgz5RylYCRDUAO0JWM48kM=</ds:DigestValue>
					</ds:Reference>
				</ds:SignedInfo>
				<ds:SignatureValue>
					NHjjgpb9/alUOq50CqPKLcdYrp7edYdKJDNvIhh+2OAhYdDvZmD1qGsVKd1H9oKPF17uaF2Sv3aY
					0le6BrvzVx3n2+nYYlHwAWlzBk7wsBt4vLll6q6juLCP+siupTIb1PeZDf3WrAbHUQh5oqjD6cZB
					Sc89pDspWRABQ8wPxYE=
</ds:SignatureValue>
				<ds:KeyInfo Id="KeyId-F5114C147B958E706212759086157652">
					<wsse:SecurityTokenReference
						xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
						wsu:Id="STRId-F5114C147B958E706212759086157673"
						xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
						<ds:X509Data>
							<ds:X509IssuerSerial>
								<ds:X509IssuerName>CN=Lukas Krecan,OU=Test</ds:X509IssuerName>
								<ds:X509SerialNumber>1275900789</ds:X509SerialNumber>
							</ds:X509IssuerSerial>
						</ds:X509Data>
					</wsse:SecurityTokenReference>
				</ds:KeyInfo>
			</ds:Signature>
			<wsu:Timestamp
				xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
				wsu:Id="Timestamp-1">
				<wsu:Created>2010-06-07T11:03:35.749Z</wsu:Created>
				<wsu:Expires>2010-06-07T11:08:35.749Z</wsu:Expires>
			</wsu:Timestamp>
		</wsse:Security>
	</SOAP-ENV:Header>
	<SOAP-ENV:Body
		xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
		wsu:Id="id-3">
		<ns2:plusRequest xmlns:ns2="http://javacrumbs.net/calc">
			<ns2:a>
				<xenc:EncryptedData Id="EncDataId-4"
					Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
					<xenc:EncryptionMethod
						Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
					<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
						<wsse:SecurityTokenReference
							xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
							<wsse:Reference URI="#EncKeyId-F5114C147B958E706212759086159355"
								xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" />
						</wsse:SecurityTokenReference>
					</ds:KeyInfo>
					<xenc:CipherData>
						<xenc:CipherValue>81TEtUhHXo6iZeAmYrtYlm2ObAqOBpjfzf2VOVUg4Hs=
						</xenc:CipherValue>
					</xenc:CipherData>
				</xenc:EncryptedData>
			</ns2:a>
			<ns2:b>2</ns2:b>
		</ns2:plusRequest>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Server config

To configure server, you have to define Spring WS server interceptor like this (full example).

<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
	<property name="interceptors">
		<list>
			<ref local="wsServerSecurityInterceptor" />
		</list>
	</property>
</bean>

<bean id="wsServerSecurityInterceptor"	class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
	<!-- Validation part -->
	<property name="validationActions" value="Timestamp Signature Encrypt"/>
	<property name="validationSignatureCrypto" ref="serverCrypto"/>
	<property name="validationDecryptionCrypto" ref="serverCrypto"/>
	<property name="validationCallbackHandler">
		<bean class="org.springframework.ws.soap.security.wss4j.callback.KeyStoreCallbackHandler">
			<property name="keyStore">
				<bean class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
				    <property name="password" value="mypasswd"/>
				</bean>
			</property>
			<property name="privateKeyPassword" value=""/>
		</bean> 
	</property>
	<!-- Sign the response -->
	<property name="securementActions" value="Signature" />
	<property name="securementUsername" value="server" />
	<property name="securementPassword" value="" />
	<property name="securementSignatureCrypto" ref="serverCrypto"/>
</bean>

<bean id="serverCrypto" class="org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean">
    <property name="keyStorePassword" value="mypasswd"/>
    <property name="keyStoreLocation" value="classpath:security/server-keystore.jks"/>
</bean>

No surprise here neither. The response will look like this.

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
	<SOAP-ENV:Header>
		<wsse:Security
			xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
			SOAP-ENV:mustUnderstand="1">
			<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
				Id="Signature-6">
				<ds:SignedInfo>
					<ds:CanonicalizationMethod
						Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
					<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
					<ds:Reference URI="#id-7">
						<ds:Transforms>
							<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
						</ds:Transforms>
						<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
						<ds:DigestValue>hEdDfxM6Nfs62Jxe8EOsELCDtUk=</ds:DigestValue>
					</ds:Reference>
					<ds:Reference URI="#SigConf-5">
						<ds:Transforms>
							<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
						</ds:Transforms>
						<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
						<ds:DigestValue>TTSRri5KJqXeMJfjzXyVmUewPxc=</ds:DigestValue>
					</ds:Reference>
				</ds:SignedInfo>
				<ds:SignatureValue>
					V5by3bOoGQNajfs7i9xQ+cbAqIkI0NS9N9FQlLb/dAuQfguE7jKRP9iypOeRLHCPr7g3BNg+NCrX
					6YcgDQ0TfXNhdL00AmoEfDmWSNvIVNE49kZEn3Ji/RW4VtdEiV79VD7Vuay0YAYGo9DSQvzq3FP6
					YEhfzfMqvfbWMdEKcO8=
</ds:SignatureValue>
				<ds:KeyInfo Id="KeyId-F5114C147B958E706212759086160837">
					<wsse:SecurityTokenReference
						xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
						wsu:Id="STRId-F5114C147B958E706212759086160838"
						xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
						<ds:X509Data>
							<ds:X509IssuerSerial>
								<ds:X509IssuerName>CN=Test Server,OU=Test</ds:X509IssuerName>
								<ds:X509SerialNumber>1275904530</ds:X509SerialNumber>
							</ds:X509IssuerSerial>
						</ds:X509Data>
					</wsse:SecurityTokenReference>
				</ds:KeyInfo>
			</ds:Signature>
			<wsse11:SignatureConfirmation
				xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd"
				xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
				Value="NHjjgpb9/alUOq50CqPKLcdYrp7edYdKJDNvIhh+2OAhYdDvZmD1qGsVKd1H9oKPF17uaF2Sv3aY0le6BrvzVx3n2+nYYlHwAWlzBk7wsBt4vLll6q6juLCP+siupTIb1PeZDf3WrAbHUQh5oqjD6cZBSc89pDspWRABQ8wPxYE="
				wsu:Id="SigConf-5" />
		</wsse:Security>
	</SOAP-ENV:Header>
	<SOAP-ENV:Body
		xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
		wsu:Id="id-7">
		<ns2:plusResponse xmlns:ns2="http://javacrumbs.net/calc">
			<ns2:result>3</ns2:result>
		</ns2:plusResponse>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

As we have seen it’s possible to configure WS-Security without much hassle. To learn more, visit the official Spring WS reference. You can download full example here.

GeeCON – část poslední

Původně jsem chtěl o GeeCONu referovat víc rovnou na místě, ale nějak jsem to nezvládl. Byl jsem tak trochu přehlcen vstupy, takže se to pokusím dohnat teď. O spoustě věcí už psal otec Fura, já se tady pokusím vypíchnout jen to, co mě zaujalo nejvíce.

Let it crash
Jonas Boner

Přednáška bylo o knihovně/frameworku Akka. Zase jsem si připomněl jak funguji aktoři a podobné záležitosti. Vypadá to hodně pěkně a použitelně.

Jelikož jsem mastodont, tak mi to hodně připomnělo vychytanější JMS, ale to se není čemu divit. Celý ten asynchronní přístup je pořád o tom samém.

Hodně se mi líbila softwarová transakční paměť (STM). S tím bych si chtěl pohrát. Možná to zatím není moc užitečné, možná to dokonce podporuje špatné návyky, ale rozhodně to vypadá jako pěkné hračka.
Z přednášky samé mě zaujala následující fakta a hlášky:

Na stroji s 4GB paměti může najednou žít 6,5 milionu aktorů.

V Erlangu umějí dosáhnout spolehlivosti na úrovni 9 devítek (99,999 999 9% dostupnosti)

Teď k vám přednáším a tím měním stav ve vašem mozku. Nedělám to tak, že bych vyndal mozek z vaší hlavy, nezměnil jeho stav a vrátil ho zpátky. (pěkné vysvětlení aktorů)

Java 7 Update
Dalibor Topic

Zajímavé povídání o Javě 7. Ale už si pomalu začínám zvykat. Rozdílem oproti obdobné přednášce na Devoxu 2008 bylo to, že některé věci už mají naimplementovány. Ale nevím, jestli mám věřit tomu, že Java 7 někdy spatří světlo světa. Uvidíme jak se k tomu postaví Oracle.
Po přednášce jsem si odchytil řečníka a snažil jsem se zjistit, jak to bude s tím modulárním systémem, který mi dost nahání hrůzu. Moc mě neuklidnil. Když jsem se ho zeptal, jak to budu dělat, když si budu chtít zvolit JDBC ovladač a nebudu mít classpath, tak mi moc neodpověděl. A to je prosím člověk, který se podílí na části implementace toho modulárního systému! Nezbývá mi, než si stáhnout OpenJDK a vyzkoušet na vlastní pěst.

Squeezing Java Performance: When you need a little more
Thomas Enebo

Hodně zajímavé, ale už to popsal otec Fura. Já jsem se tam dozvěděl, že dlouhé metody nejsou špatné jen z důvodu čitelnosti, ale že s nimi má problém i JVM. Takže tady má dobrý návrh bod k dobru. Bohužel jsem se taky dozvěděl, že za určitých okolností JVMku nedělá dobře polymorfismus, ale to mě neodradí od toho ho používat. (Slyšel jste někdo někdy o tzv. „megamorphic“ stavu? Já poprvé až na GeeCONu).

Apache Camel as a DSL for system integration
Roman Kalukiewicz

Camel mě docela překvapil. Původě jsem myslel, že to je jeden z mnoha dalších ESB nástrojů, ale nakonec jsem zjistil, že je to umí něco navíc. Přednáška se točila kolem jejich DSL, který umožňuje celý ten proces elegantně popsat. Například:

from("jms:aQueue")
  .filter().xpath("/person[@name='Jon']")
  .to("file:c:\tmp");

Snad ani nebudu vysvětlovat, co to dělá, je to samopopisné. Největší legrace je, že mi stačí napsat podobných pár řádků a už se to dá spustit z main metody. Samozřejmě se to dá i zaintegrovat do vašeho oblíbeného serveru. Další věc na kterou se chci podívat.

Abych to shrnul, GeeCON příjemně překvapil. Sice tam nabylo tolik špičkovách řečníků jako třeba na Devoxxu, ale i tak se tam člověk dozvěděl neuvěřitelné množství věcí. Už mám seznam věcí, na které se chci rozhodně podívat. Je vidět, že v oblasti Javy se docela inovuje, i když souhlasím s Dagim, že Jazyk samotný nám tak trochu stagnuje.