Keep It Simple
Some plain old Java object magic
Today I read an article about how to send an HTTP request and parse the XML response using JavaFX [1]. Being used to plain old Java syntax the code examples from the article looked unfamiliar and not very clear.
I thought why not write a similar article about how to do the same with plain old Java? So here it is: How to send a HTTP request and read an XML response with plain old Java.
Certainly you now might say, hey, that's pretty much code, why not just use the JavaFX version? Well, that's the amazing thing with Java classes, they're reusable. With above class now existing [2] all you actually need is one line of code whenever you like to send a HTTP request:
As in the JavaFX example [1] I use my own Java XML parser instead of the one sometimes packaged with the JRE. It is my own parser but it works comparable to the SAXParser. My parser is included in the example sources [2].
With class XmlReader again only a single line of code is needed wherever an XML response should be processed:
to send an HTTP request and process its XML response. No FX, no fancy schmancy frameworks or class libraries required. Just two plain old simple Java classes.
[2] Example Source Codes
I thought why not write a similar article about how to do the same with plain old Java? So here it is: How to send a HTTP request and read an XML response with plain old Java.
How to send a HTTP request
To send a HTTP request we create a class HttpRequest as followspublic class HttpRequest {
public HttpRequest() {
super();
}
public static InputStream get(String urlStr) throws Exception {
return readFrom(urlStr, null);
}
public static InputStream post(String urlStr, String post)
throws Exception
{
return readFrom(urlStr, post);
}
private static InputStream readFrom(String urlStr, String post)
throws MalformedURLException, IOException
{
URLConnection conn = new URL(urlStr).openConnection();
conn.setConnectTimeout(15000);
conn.setReadTimeout(15000);
conn.setDoInput(true);
if (post != null && post.length() > 0) {
conn.setDoOutput(true);
DataOutputStream output =
new DataOutputStream(conn.getOutputStream());
output.writeBytes(post);
output.flush();
output.close();
}
return conn.getInputStream();
}
}
public HttpRequest() {
super();
}
public static InputStream get(String urlStr) throws Exception {
return readFrom(urlStr, null);
}
public static InputStream post(String urlStr, String post)
throws Exception
{
return readFrom(urlStr, post);
}
private static InputStream readFrom(String urlStr, String post)
throws MalformedURLException, IOException
{
URLConnection conn = new URL(urlStr).openConnection();
conn.setConnectTimeout(15000);
conn.setReadTimeout(15000);
conn.setDoInput(true);
if (post != null && post.length() > 0) {
conn.setDoOutput(true);
DataOutputStream output =
new DataOutputStream(conn.getOutputStream());
output.writeBytes(post);
output.flush();
output.close();
}
return conn.getInputStream();
}
}
Certainly you now might say, hey, that's pretty much code, why not just use the JavaFX version? Well, that's the amazing thing with Java classes, they're reusable. With above class now existing [2] all you actually need is one line of code whenever you like to send a HTTP request:
InputStream is = HttpRequest.get("http://www.java.net");
How to read an XML response
The same applies for reading the response from a HTTP request that is returned in XML format. We simply create an XML reader class that is reusable for any XML response.public class XmlReader implements XmlParserCallback {
public XmlReader() {
super();
}
public void read(InputStream is) throws IOException, IllegalCharacterException {
XmlParser parser = new XmlParser(this);
BufferedReader r = new BufferedReader(new InputStreamReader(is));
String line = r.readLine();
while (line != null) {
parser.parse(line);
line = r.readLine();
}
r.close();
}
public void handleStartTag(String tagName, AttributeSet a) {
System.out.println("start tag " + tagName);
}
public void handleEndTag(String tagName) {
System.out.println("end tag " + tagName);
}
public void handleText(String text) {
if(text != null && text.trim().length() > 0) {
System.out.println("text " + text);
}
}
}
public XmlReader() {
super();
}
public void read(InputStream is) throws IOException, IllegalCharacterException {
XmlParser parser = new XmlParser(this);
BufferedReader r = new BufferedReader(new InputStreamReader(is));
String line = r.readLine();
while (line != null) {
parser.parse(line);
line = r.readLine();
}
r.close();
}
public void handleStartTag(String tagName, AttributeSet a) {
System.out.println("start tag " + tagName);
}
public void handleEndTag(String tagName) {
System.out.println("end tag " + tagName);
}
public void handleText(String text) {
if(text != null && text.trim().length() > 0) {
System.out.println("text " + text);
}
}
}
As in the JavaFX example [1] I use my own Java XML parser instead of the one sometimes packaged with the JRE. It is my own parser but it works comparable to the SAXParser. My parser is included in the example sources [2].
With class XmlReader again only a single line of code is needed wherever an XML response should be processed:
new XmlReader().read(is);
Conclusion
With two simple classes HttpRequest and XmlReader all you actually need to do isInputStream is = HttpRequest.get("http://www.java.net");
new XmlReader().read(is);
to send an HTTP request and process its XML response. No FX, no fancy schmancy frameworks or class libraries required. Just two plain old simple Java classes.
References
[1] JavaFX HTTP Networking and XML Parsing[2] Example Source Codes
Holidays Refined
An update for the World Holiday Calendar Service
Last June I blogged about the re-engineered version of my World Holiday Calendar Service. I have now adapted the client API to further simplify access to the service for third party applications and published the new version of the class library here. I thought I give an overview of the finished service in below diagram

On the back end, no static date tables need to be maintained. The holiday class library dynamically computes dates of occurrence for arbitrary days and provides them to the various services offered.
What started as a wacky habit became a system independent and universal tool for worldwide holiday determination.

The Light Development World Holiday Calendar Service
On the back end, no static date tables need to be maintained. The holiday class library dynamically computes dates of occurrence for arbitrary days and provides them to the various services offered.
What started as a wacky habit became a system independent and universal tool for worldwide holiday determination.
Mark II
Jetzt ist es amtlich: Kein Kamerakauf auf absehbare Zeit
Canon hat im Spätsommer/Herbst 2008 einen großen Erwartungsdruck bei Canoniten hervorgerufen, als die Gerüchte, ein Nachfolgemodell der EOS 5D auf der Photokina zu präsentieren, bestätigt wurden. Alle waren vollkommen aus dem Häuschen und jeder wollte das neue Flaggschiff haben.
Ich habe auch überlegt, ob ich meine 5D mit dem neuen Modell ersetze, war aber enttäuscht, so wenig Handfestes zur Bildqualität zu erfahren. Wegen der großen Nachfrage konnte man auch nach der Vorstellung auf der Photokina lange Zeit keine Testberichte finden, geschweige denn, ein Modell testhalber selbst in Augenschein nehmen.
Auf der Grundlage der reinen technischen Daten habe ich seinerzeit den Eindruck gewonnen, daß für mich ein Umstieg nicht genügend Nutzen bereithält, um die Kosten der Neuanschaffung aufzuwiegen.
Nun ist die Analyse der Canon EOS 5D Mark II auf dpreview erschienen und bestätigt meinen Eindruck. Nach einem guten halben Jahr gibt es endlich die Grundlage für eine fundierte Kaufentscheidung.
Die 5D und ihr Nachfolgemodell unterscheiden sich in Dynamikumfang und Bildqualität nicht sehr. Der größte Unterschied ist, daß die Mark II bei weitaus größerer Auflösung (21 MP vs. 12 MP) besseres Rauschverhalten aufweist. Zudem hat das neue Modell eine größere Lichtempfindlichkeit.
Mein Fazit
Die Canon EOS 5D Mark II ist eine konsequente Weiterentwicklung der 5D und setzt drei Jahre nach der Vorstellung ihrer Vorgängerin erneut die Marke für digitale Vollformatkameras in puncto Auflösung und Bildqualität.
Die 5D Mark II ist das Modell der Wahl für jeden Fotografen, der sich von einer 'Crop Kamera' in Richtung Vollformat verändern möchte, also für Besitzer der Modelle 300, 350, 400, 450, 10, 20, 30, 40 D.
Nutzer einer 5D dagegen sollten sich den Schritt genau überlegen. In drei Jahren sieht die digitale Welt schon wieder anders aus und bis dahin steht die 5D kaum hinter ihrer Nachfolgerin zurück.
Ich habe auch überlegt, ob ich meine 5D mit dem neuen Modell ersetze, war aber enttäuscht, so wenig Handfestes zur Bildqualität zu erfahren. Wegen der großen Nachfrage konnte man auch nach der Vorstellung auf der Photokina lange Zeit keine Testberichte finden, geschweige denn, ein Modell testhalber selbst in Augenschein nehmen.
Auf der Grundlage der reinen technischen Daten habe ich seinerzeit den Eindruck gewonnen, daß für mich ein Umstieg nicht genügend Nutzen bereithält, um die Kosten der Neuanschaffung aufzuwiegen.
Nun ist die Analyse der Canon EOS 5D Mark II auf dpreview erschienen und bestätigt meinen Eindruck. Nach einem guten halben Jahr gibt es endlich die Grundlage für eine fundierte Kaufentscheidung.
Die 5D und ihr Nachfolgemodell unterscheiden sich in Dynamikumfang und Bildqualität nicht sehr. Der größte Unterschied ist, daß die Mark II bei weitaus größerer Auflösung (21 MP vs. 12 MP) besseres Rauschverhalten aufweist. Zudem hat das neue Modell eine größere Lichtempfindlichkeit.
Mein Fazit
Die Canon EOS 5D Mark II ist eine konsequente Weiterentwicklung der 5D und setzt drei Jahre nach der Vorstellung ihrer Vorgängerin erneut die Marke für digitale Vollformatkameras in puncto Auflösung und Bildqualität.
Die 5D Mark II ist das Modell der Wahl für jeden Fotografen, der sich von einer 'Crop Kamera' in Richtung Vollformat verändern möchte, also für Besitzer der Modelle 300, 350, 400, 450, 10, 20, 30, 40 D.
Nutzer einer 5D dagegen sollten sich den Schritt genau überlegen. In drei Jahren sieht die digitale Welt schon wieder anders aus und bis dahin steht die 5D kaum hinter ihrer Nachfolgerin zurück.
Audioserver für den Hausgebrauch
Die 'etablierten' Hersteller haben wieder mal gepennt
Warum gibt es eigentlich keine Browserfernsteuerung, die es erlaubt, Playlisten auf dem Musikserver zu erstellen und abzuspielen? TwonkyMusic, VLC, Nero, Media Player, usw. - alles Kappes. Ich habe mir jetzt eine ganz simple selbst gebaut, die gleich auch noch die gerade gespielten Titel an Last.fm übermittelt.
Im Browser ruft man die Adresse der Anwendung auf, z.B.
Anschließend ruft man einfach mit dem Abspielgerät seiner Wahl die Adresse des zur Playlist gehörenden Kanals auf, z.B.
So. Hat doch garnicht weh getan. Und warum gibt es das nicht schon längst? Von mir gibt es das hier.
Im Browser ruft man die Adresse der Anwendung auf, z.B.
http://192.168.178.21/HomeAudio/und gibt seine User ID ein. Diese wird einmalig auf dem Server hinterlegt und dient dazu, die Playlisten einzelner Benutzer voneinander getrennt zu halten. Jeder Benutzer kann eine beliebige Anzahl von "Kanälen" benennen und zu jedem Kanal eine Playlist zusammenstellen.
Anschließend ruft man einfach mit dem Abspielgerät seiner Wahl die Adresse des zur Playlist gehörenden Kanals auf, z.B.
http://192.168.178.21/HomeAudio/Server/play/kanal1Die Playlist kann jederzeit im Webbrowser verändert werden, auch während die Musik spielt.
So. Hat doch garnicht weh getan. Und warum gibt es das nicht schon längst? Von mir gibt es das hier.