Streaming a stream

I have another dirty trick for you. Let’s imagine that you have a document server with following sophisticated interface.

public interface DocumentServer {
	/**
	 * Stores a document.
	 * @return document id
	 */
	public String storeDocument(InputStream in);
	
	/**
	 * Loads document with given id.
	 * @param id
	 * @return
	 */
	public InputStream loadDocument(String id);
}

It works well, until you realize, that you want to call the DocumentServer remotely, for example using Spring HttpInvoker.

HttpInvoker is a nice small tool, that lets you make remote method invocations over HTTP without much pain. It creates dynamic proxy, serializes all attributes using Java serialization, calls remote proxy, which deserializes arguments, calls the implementation and sends the result back in the same way. It is nice, simple and it works without any problem. You can configure it in five minutes. The downside is, that you have to have Spring Java application on both ends of the wire and all arguments that you send over the wire have to be Serializable.

And that’s exactly the trouble we have with our DocumentServer. There is no standard InputStream implementation that implements serializable. Lets think about it. We need to have a stream that is able to stream itself into an ObjectOutputStream. Sounds strange, but it is quite easy. We can simply write a wrapper, that implements writeObject(ObjectOutputStream) method and that takes all the bytes from the underlying stream and writes them to the ObjectOutputStream. It is simple and it does not consume much memory.

Deserialization is much harder. We have to implement readObject(ObjectInputStream in) method, load the data and store them somewhere for later use. We can store them in the memory or in a temporary file. If the streams are larger, temporary file is better choice but we have to delete them after use and the implementation gets messy.

The good news is, that we do not have to implement it, it’s already done by RMIIO library. They provide SerializableInputStream class that does exactly what we need. You just have to ignore Javadoc comment saying:

An additional layer around a RemoteInputStream which makes it Serializable and an InputStream. In general, this extra layer is not necessary and I do not recommend using this class. However, in the odd case where the callee really wants to get something which is already an InputStream, this class can be useful.

The only thing we have to do is to wrap all the streams into SerializableInputStream like this

new SerializableInputStream(new DirectRemoteInputStream(inputStream));

It can be done by hand written proxy, by dynamically generated proxy or by AOP.

Of course there are other alternatives. The easiest one is to create something like ByteArayInputStream that implements Serializable. If the streams are small enough, it’s the best solution.

We can also try to use Hessian, but I had some troubles when method signatures were more complicated. And of course there is still a possibility to implement own remoting mechanism. After all, HTTP is meant to transport streams. But it would require lot of boilerplate code and I do not like boilerplate code.

Rok s Linuxem

Kdysi jsem tu psal jak jsem nepřešel na Linux. Dnes chci psát pravý opak. Zanedlouho oslavím rok s Linuxem, takže bych se chtěl podělit o zkušenosti.

Začalo to nenápadně. Koupil jsem si nový notebook s předinstalovanými Windows XP. Jenže počítač hrozně pomalu startoval a vypnout se nechtěl vůbec. Při vypínání vyhazoval okýnka tvrdící, že se aplikace nemůže nastartovat protože se počítač vypíná. Možná za to nemohly Windows, možná za to mohl crapware od Lenova, který tam byl nainstalován. Pravděpodobně by pomohla reinstalace, ale řekl jsem si, že když už to budu přeinstalovávat, tak tam už rovnou můžu šoupnout Linux. Tenkrát zrovna vyšlo Ubuntu 8.04, tak jsem ho nainstaloval a od té doby ho spokojeně používám (teď už ve verzi 8.10).

Začnu chválou. Pro pracovní účely je to naprosto ideální. Mám fungující shell, který nezapomíná historii příkazů, Java běhá jak po drátkách, Eclipse jede taky bez větších problémů. A to jsem pěkně prosím masochista, který si nainstaloval ode všeho 64 bitovou verzi. Jediné co mi nejde je GWT. To bych musel nainstalovat Javu a Eclipse v 32 bitové verzi, což se mi nechtělo.

Z nesvobodného softwaru taky funguje všechno co potřebuji. Třeba Skype funguje bez problémů i s videem. Google Picasa je ošklivá, ale co se funkčnosti týče, taky jí nic nechybí. Od té doby co mám OpenOffice 3.0 není ani moc problém pracovat s dokumenty z Office 2007. Ale to naštěstí tak často nepotřebuji.

Samozřejmě všechno nebyla jen procházka růžovým sadem. Podpora hardware není stoprocentní. Standardní HW jede bez problému, ty nastávají až s exotičtějšími periferiemi. Čtečku otisků prstů jsem nerozjel vůbec, ale to mě vůbec netrápí. Jediný případ, kdy jsem musel něco kompilovat, byl ovladač pro televizní USB kartu. Ale to šlo víceméně taky samo. Jinak všechno funguje jak má, možná ještě lépe než ve Windows. Dokonce i 3G připojení přes Windows Mobile telefon na USB jede jak po másle.

Problém je občas s přehráváním DVD. Některá DVD mi prostě Linux nepřehraje. Možná je to ovladačem mechaniky, možná kodeky. Nevím, ale to je taky okrajová věc. Co se týče multimédií, Flash je bez problému, portál České televize chce trochu laborování s pluginy do Firefoxu (doporučuji MediaPlayerConnectivity a VLC). Když se člověk nainstaluje Kaffeine, tak mu pak pěkně jede i ta digitální televize.

Bezchybně funguje i hibernace a suspend režim. Bohužel proces probuzení tak bezchybný není. Hodně často se stává, že se počítač nějak nechce probudit. To mi asi vadí nejvíc.

Ale jinak se musím zopakovat. Pokud nejste nuceni používat nějaký SW, který je jen pro Windows, Linux už je docela obstojná alternativa. A musím se přiznat, že mi vyhovuje mnohem více. Působí na mě svižnějším dojmem, člověk nemusí čekat, až se nastartují všechny antiviry, firewally, ovládací software od všeho možného. Nedávno jsem si nainstaloval Windows XP do virtuálu, a to je naprosto super. Používáte Linux a když sem tam něco potřebujete vyzkoušet ve Windows tak si je pustíte v okně. Pokud potřebuje Internet Explorer, tak verze šest se dá docela bezbolestně rozjet pod Wine (doporučuji ies4linux). Tady jen musím upozornit, že jak u Wine tak u virtuálu je potřeba si dát pozor na licence.

Abych to shrnul, Linux je pro vývoj v Javě naprosto plnohodnotný, je ale bezpečnější zvolit 32 bitovou verzi. Problém může být proprietární software. Například Enterprise Architekt prý jede jen pod emulací. Pocitově mi Linux vyhovuje mnohem více než Windows. A pokud nemáte neobvyklý HW, tak se není ani moc čeho bát.

Ušetřím vám práci s psaním komentářů, vím že Apple je mnohem lepší, všechno se dá ovládat pouhou myšlenkou a navíc s ním průměrný programátor vypadá mnohem víc sexy. Já jsem ale dost sexy i bez Jablíčka a navíc jsem ten divný brouk, který docela dbá na ten naprosto neužitečný a nepopsatelný pocit svobody. Takže se budu snažit ještě chvíli vzdorovat.

InfoQ

Dnes jsem zjistil, že ne všichni vědí o existenci zajímavého zdroje informací. Jmenuje se InfoQ a najdete tam spoustu užitečných článků, videí a rozhovorů ze světa Javy, .NETu a agilních technik.

Tento týden tam například vyšel naprosto dokonalý článek o modulárním systému, který má být součástí Javy 7. Ten si určitě přečtěte, napsal jsem ho totiž já. Sice mi ho editor trochu překopal, ale i tak můžete být oslněni záblesky mé geniality. Gratulace a šeky posílejte prosím poštou.