<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>BadMagicNumber &#187; java</title>
	<atom:link href="http://nicklothian.com/blog/category/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://nicklothian.com/blog</link>
	<description>My Blog, Take 4</description>
	<lastBuildDate>Wed, 18 Jan 2012 13:55:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>A pragmatic approach to Google AppEngine</title>
		<link>http://nicklothian.com/blog/2010/11/23/a-pragmatic-approach-to-google-appengine/</link>
		<comments>http://nicklothian.com/blog/2010/11/23/a-pragmatic-approach-to-google-appengine/#comments</comments>
		<pubDate>Wed, 24 Nov 2010 01:31:52 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[appengine]]></category>
		<category><![CDATA[gae]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=462</guid>
		<description><![CDATA[I&#8217;ve been working on a large (Java) AppEngine project since January 2010. I recently left that job, but the project hasn&#8217;t finished and unfortunately I can&#8217;t talk about it yet. During that time I learnt a lot of tricks and techniques for dealing with AppEngine&#8217;s idiosyncrasies, which have been useful for building a contextual advertising demo system: [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a large (Java) AppEngine project since January 2010. I recently left that job, but the project hasn&#8217;t finished and unfortunately I can&#8217;t talk about it yet.</p>
<p>During that time I learnt a lot of tricks and techniques for dealing with AppEngine&#8217;s idiosyncrasies, which have been useful for building a contextual advertising demo system: <a href="http://demo.qontex.com">Qontex.com</a> (brief synopsis: contextual affiliate ad distribution software. Not too sure what I&#8217;m going to do with it, but I had fun building it. The front end container is actually WordPress(!), but the UI is GWT and the backend is AppEngine).</p>
<p>Anyway, it seems useful to share a few things I&#8217;ve learnt.</p>
<p><strong>1) Be pragmatic</strong></p>
<p>I think of AppEngine as Amazon S3 plus some intelligence, rather than Amazon EC2 minus features. I find that a lot less frustrating.</p>
<p>If there is something you need that AppEngine doesn&#8217;t do well, don&#8217;t try and force it. Full Text Search is a great example: it&#8217;s horrible to try &amp; get it to work on AppEngine, but installing Solr on a VM somewhere (or using a cloud Solr provider) is trivial.</p>
<p><strong>2) AppEngine is a platform optimized for a specific type of application.</strong></p>
<p>Don&#8217;t think of AppEngine as a standard Java application stack in the cloud. From the documentation:</p>
<blockquote><p><em>While a request can take as long as 30 seconds to respond, App Engine is optimized for applications with short-lived requests, typically those that take a few hundred milliseconds. An efficient app responds quickly for the majority of requests. An app that doesn&#8217;t will not scale well with App Engine&#8217;s infrastructure.</em></p></blockquote>
<p>Think about that for a while, and understand it well. Often Java developers are used to building corporate web apps where functionality is slowly built up over time. All too often a single HTTP request will have 4 or 5 database queries in it, and that is regarded as normal. That won&#8217;t work in AppEngine.</p>
<p>When you are working with AppEngine you&#8217;ll be thinking about performance continually, and differently to how you do with a normal Java application.</p>
<p><strong>3) The datastore is dangerous. </strong></p>
<p>In the development environment it has similar performance characteristics to a traditional database. In production it is slow at best, unpredictable at worst. If you come from an enterprise Java background, think of it as an integration server for a legacy API you are integrating with: data inside it isn&#8217;t going to go missing, but you should expect your connection to it will break at any point. You need to isolate your users from it, protect you application from it and consider carefully how to protect your data from outages.</p>
<p>I usually assume that a datastore query is going to take 200ms. Lately it has usually been better than that, but the variation is still a problem: <a href="http://code.google.com/status/appengine/detail/datastore/2010/11/23#ae-trust-detail-datastore-query-latency">http://code.google.com/status/appengine/detail/datastore/2010/11/23#ae-trust-detail-datastore-query-latency</a></p>
<p><strong>4) Memcache is useful, but no silver bullet.</strong></p>
<p>Memcache is useful because it has much more predictable performance characteristics than the datastore &#8211; and it&#8217;s a lot faster too. Generally, it&#8217;s pretty safe to rely on Memcache responding in less than 20ms at worst. At the moment its responses are around 5-10ms. See the Memcache status page for details: <a href="http://code.google.com/status/appengine/detail/memcache/2010/11/23#ae-trust-detail-memcache-get-latency">http://code.google.com/status/appengine/detail/memcache/2010/11/23#ae-trust-detail-memcache-get-latency</a></p>
<h2>A Useful Pattern</h2>
<p>One pattern I&#8217;ve found useful is to think of user-facing servlets as similar to the UI thread in a GUI application. Blocking should be kept minimal, and anything that&#8217;s going to take significant time is done from task queues. This includes anything beyond a single &#8220;GET&#8221; on the datastore (note that a GET operation is very roughly twice as fast as a datastore query)</p>
<p>For example Qontex has a process that relies on content analysis. I currently do that on-demand rather than attempting to spider the entire internet. The demo &#8220;Ad Explorer&#8221; front end is written in GWT, and it works like this:</p>
<p>1) Send a request to the analyze URL, passing the name of a callback function (for JSONP callback)</p>
<p>2) The backend checks Memcache for data about the URL. If it isn&#8217;t there, it fires an AppEngine task queue request to analyze the URL and returns a JSONP response that contains a <em>status_incomplete</em> flag and a <em>wait_seconds</em> parameter.</p>
<p>3) The GWT client gets the response, and sets a timer to re-request in <em>wait_seconds</em> seconds.</p>
<p>4) Meanwhile, back on the server the task queue task is being processed. That task will load the results into memcache.</p>
<p>5) The client re-requests the analyze URL, and this time Memcache has been loaded so the servlet can built a response with the correct data.</p>
<p>I use a similar, but simpler pattern to write to the datastore.</p>
<p>When an ad is served, or when a user clicks an ad I fire a task-queue request to record that, which lets me send a response much quicker. AppStats is great for showing this graphically:</p>
<p><a href="http://nicklothian.com/blog/wp-content/uploads/2010/11/appstats.png"><img class="alignnone size-medium wp-image-463" title="appstats" src="http://nicklothian.com/blog/wp-content/uploads/2010/11/appstats-300x48.png" alt="" width="300" height="48" /></a></p>
<p>As you can see there it would be sensible to bulk up all those memcache reads into a single read on a composite object. At the same time, the entire servlet responds on 37ms, which isn&#8217;t too bad, and some of those memcache calls are conditional &#8211; but the point is that AppStats gives great visibility into exactly how your application is performing.</p>
]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2010/11/23/a-pragmatic-approach-to-google-appengine/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Solr+Cassandra</title>
		<link>http://nicklothian.com/blog/2009/10/27/solr-cassandra-solandra/</link>
		<comments>http://nicklothian.com/blog/2009/10/27/solr-cassandra-solandra/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 03:15:21 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[cassandra]]></category>
		<category><![CDATA[solr]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=392</guid>
		<description><![CDATA[I&#8217;ve been a big fan of Solr for quite a long time, and have used it extensively at work. I noticed a few weeks ago that Jake Luciani had managed to get Lucene (which Solr uses) working on Cassandra (Facebook&#8217;s highly scalable keystore). The next step had an obvious name: Solandra &#8211; Solr running on [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been a big fan of <a href="http://lucene.apache.org/solr/">Solr</a> for quite a long time, and have used it extensively at work.</p>
<p>I noticed a few weeks ago that <a href="http://3.rdrail.net/blog/">Jake Luciani</a> had managed to get Lucene (which Solr uses) <a href="http://github.com/tjake/Lucandra">working </a>on <a href="http://incubator.apache.org/cassandra/">Cassandra</a> (Facebook&#8217;s highly scalable keystore).</p>
<p>The next step had an obvious name: Solandra &#8211; Solr running on Cassandra.</p>
<p>Basically there wasn&#8217;t too much to getting it going in the limited form it is now &#8211; a few minor changes to Jake&#8217;s Lucandra code, a custom Solr FieldType (exactly why I needed this I&#8217;m unsure) and correctly configured solrconfig.xml and schema.xml files.</p>
<p>I haven&#8217;t tested updates, so you&#8217;ll probably need Jake&#8217;s <a href="http://github.com/tjake/Lucandra/blob/master/test/lucandra/demo/BookmarksDemo.java">BookmarkDemo</a> to load data in.</p>
<p>My changes to the Lucandra index reader include hard coding (!) the fields returned by getFieldNames(..) to match the Solr schema and the fields added in the demo.</p>
<p>If anyone is interested, the code is available: <a href="http://nicklothian.com/files/solandra28102009.zip">solandra.zip</a>. You&#8217;ll need to be a Java developer to use it, though.</p>
]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/10/27/solr-cassandra-solandra/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>The AppEngine is forking Java &#8220;controversy&#8221;</title>
		<link>http://nicklothian.com/blog/2009/04/13/the-appengine-is-forking-java-controversy/</link>
		<comments>http://nicklothian.com/blog/2009/04/13/the-appengine-is-forking-java-controversy/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 01:01:00 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=370</guid>
		<description><![CDATA[So there has been some noise from Sun about how Google AppEngine is evil because it&#8217;s not supporting the complete set of classes in the JRE. I&#8217;m sorry Sun &#8211; I&#8217;m a Java programmer, and I think that argument is shit. I&#8217;d much prefer a partial Java implementation with well defined limitations than PHP, or [...]]]></description>
			<content:encoded><![CDATA[<p>So there has been some noise from Sun about how Google AppEngine is evil because it&#8217;s not supporting the complete set of classes in the JRE. I&#8217;m sorry Sun &#8211; I&#8217;m a Java programmer, and I think that argument is shit. I&#8217;d much prefer a partial Java implementation with well defined limitations than PHP, or Python or Ruby.</p>
<p>AFAIK, no one has posted a list of classes missing. I can&#8217;t be bothered doing that either, but I did manually take a look at package level. Here&#8217;s it looks like GAE/J is missing:</p>
<p>java.applet<br />
java.awt.*<br />
javax.activation<br />
javax.imageio.*<br />
javax.jws.*<br />
javax.management.*<br />
javax.naming.*<br />
javax.net.*<br />
javax.print.*<br />
javax.rmi.*<br />
javax.sound.*<br />
javax.swing.*<br />
javax.tools<br />
javax.xml.bind.*<br />
javax.xml.crypto.*<br />
javax.xml.soap<br />
javax.xml.stream.*<br />
javax.xml.ws<br />
org.ietf.jgss<br />
org.omg.*</p>
<p>From that list, I&#8217;d like to see javax.activation, javax.management and the remaining javax.xml.* and maybe javax.tools packages supported. The rest really don&#8217;t seem at all relevant to the AppEngine environment.</p>
]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/04/13/the-appengine-is-forking-java-controversy/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Random MP3 metadata code</title>
		<link>http://nicklothian.com/blog/2009/03/18/random-mp3-metadata-code/</link>
		<comments>http://nicklothian.com/blog/2009/03/18/random-mp3-metadata-code/#comments</comments>
		<pubDate>Wed, 18 Mar 2009 09:08:59 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=364</guid>
		<description><![CDATA[I&#8217;ve been doing random MP3 metadata work lately. Here&#8217;s some code which others might find useful. Extracting MP3 tags from mp3 file hosted on server using HTTP Range queries. So I was using Apache Tika for various metadata stuff. I wanted to get the song title for a file hosted on a server, but Tika [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been doing random MP3 metadata work lately. Here&#8217;s some code which others might find useful.</p>
<p><strong>Extracting MP3 tags from mp3 file hosted on server using HTTP Range queries.</strong></p>
<p>So I was using <a href="http://lucene.apache.org/tika/">Apache Tika</a> for various metadata stuff. I wanted to get the song title for a file hosted on a server, but Tika only supports MP3 ID3v1 metadata, which exists at the end of a file. Downloading an entire MP3 just for the title is wasteful, but fortunatly HTTP Range queries can help us out.</p>
<p><tt></p>
<pre>HttpClient httpClient = new HttpClient();
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(10000);
httpClient.getHttpConnectionManager().getParams().setSoTimeout(10000);

String address = "http://address of mp3 file here";

HttpMethod method = new HeadMethod();
method.setURI(new URI(address,true));

Header contentLengthHeader = null;
Header acceptHeader = null;

httpClient.executeMethod(method);
try {
	//System.out.println(Arrays.toString(method.getResponseHeaders()));
	contentLengthHeader = method.getResponseHeader("Content-Length");
	acceptHeader = method.getResponseHeader("Accept-Ranges");
} finally {
	method.releaseConnection();
}

if ((contentLengthHeader != null) &amp;&amp; (acceptHeader != null) &amp;&amp; "bytes".equals(acceptHeader.getValue())) {
	long contentLength = Long.parseLong(contentLengthHeader.getValue());
	long metaDataStartRange = contentLength - 128;
	if (metaDataStartRange &gt; 0) {
		method = new GetMethod();
		method.setURI(new URI(address,true));
		method.addRequestHeader("Range", "bytes=" + metaDataStartRange + "-" + contentLength);
		System.out.println(Arrays.toString(method.getRequestHeaders()));
		httpClient.executeMethod(method);
		try {
			Parser parser = new AutoDetectParser();

			Metadata metadata = new Metadata();
			metadata.set(Metadata.RESOURCE_NAME_KEY, address);
			InputStream stream = method.getResponseBodyAsStream();
			try {
				parser.parse(stream, new DefaultHandler(), metadata);
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				stream.close();
			}
			System.out.println(Arrays.toString(metadata.names()));
			System.out.println("Title: " + metadata.get("title"));
			System.out.println("Author: " + metadata.get("Author"));
		} finally {
			method.releaseConnection();
		}
	}
} else {
	System.err.println("Range not supported. Headers were: ");
	System.err.println(Arrays.toString(method.getResponseHeaders()));
}
</pre>
<p></tt></p>
<p>The next thing I needed to do was extract song titles from a shoutcast stream. Shoutcast streams are kinda-but-not-quite http. Metadata is embedded in the stream (not as part of the MP3). That makes the code pretty ugly, but whatever&#8230; This code will open a connection, read the metadata and close, so you don&#8217;t need to keep downloading gigs of data.
</p>
<p><tt></p>
<pre>
URL url = new URL("http://scfire-ntc-aa01.stream.aol.com:80/stream/1074");
URLConnection con = url.openConnection();
con.setRequestProperty("Icy-MetaData", "1");

InputStream stream = con.getInputStream();
try {

	BufferedReader in = new BufferedReader(new InputStreamReader(stream));

	String metaIntervalString = null;
	// get the headers
	StringBuilder headers = new StringBuilder();
	char c;
	while ((c = (char)in.read()) != -1) {
		headers.append(c);
		if (headers.length() > 5 &#038;&#038; (headers.substring((headers.length() - 4), headers.length()).equals("\r\n\r\n"))) {
			// end of headers
			break;
		}
	}

	//System.out.println(headers);
	// headers look like this:
	//		ICY 200 OK
	//		icy-notice1: <BR>This stream requires <a href="http://www.winamp.com/">Winamp</a><BR>
	//		icy-notice2: Firehose Ultravox/SHOUTcast Relay Server/Linux v2.6.0<BR>
	//		icy-name: .977 The 80s Channel
	//		icy-genre: 80s Pop Rock
	//		icy-url: http://www.977music.com
	//		content-type: audio/mpeg
	//		icy-pub: 1
	//		icy-metaint: 16384
	//		icy-br: 128

	Pattern p = Pattern.compile("\\r\\n(icy-metaint):\\s*(.*)\\r\\n");
	Matcher m = p.matcher(headers.toString());
	if (m.find()) {
		metaIntervalString = m.group(2);
	}

	if (metaIntervalString != null) {
		int metaInterval = Integer.parseInt(metaIntervalString.trim());

		if (metaInterval > 0) {
			int b;
			int count = 0;
			int metaDataLength = 4080; // 4080 is the max length
			boolean inData = false;
			StringBuilder metaData = new StringBuilder();
			while ((b = stream.read()) != -1) {
				count++;

				if (count == metaInterval + 1) {
					metaDataLength = b * 16;
				}

				if (count > metaInterval + 1 &#038;&#038; count < (metaInterval + metaDataLength)) {
					inData = true;

				} else {
					inData = false;
				}

				if (inData) {
					if (b != 0) {
						metaData.append((char)b);
					}
				}

				if (count > (metaInterval + metaDataLength)) {
					break;
				}

			}
			String metaDataString = metaData.toString();
			System.out.println(metaDataString);
		}
	}
} finally {
	stream.close();
}
</pre>
<p></tt></p>
]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/03/18/random-mp3-metadata-code/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ROME 1.0 Released</title>
		<link>http://nicklothian.com/blog/2009/03/11/rome-10-released/</link>
		<comments>http://nicklothian.com/blog/2009/03/11/rome-10-released/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 00:47:43 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[ROME]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=360</guid>
		<description><![CDATA[I&#8217;ve just pushed out ROME 1.0 and ROME Fetcher 1.0. As they say with open source projects &#8211; &#8220;it&#8217;s done when it&#8217;s done&#8221;. But nearly 5 years to get to version 1.0 is kind of long.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just pushed out <a href="http://rome.dev.java.net/">ROME 1.0</a> and <a href="http://wiki.java.net/bin/view/Javawsxml/RomeFetcher">ROME Fetcher 1.0</a>.</p>
<p>As they say with open source projects &#8211; &#8220;it&#8217;s done when it&#8217;s done&#8221;. But nearly 5 years to get to version 1.0 is kind of long.</p>
]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/03/11/rome-10-released/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ROME 1.0RC2 Release</title>
		<link>http://nicklothian.com/blog/2009/01/08/rome-10rc2-release/</link>
		<comments>http://nicklothian.com/blog/2009/01/08/rome-10rc2-release/#comments</comments>
		<pubDate>Fri, 09 Jan 2009 02:46:50 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[ROME]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=353</guid>
		<description><![CDATA[I&#8217;ve just pushed out a release of ROME core, ROME Fetcher and ROME modules. For those who don&#8217;t know, ROME is a (the?) Java library for handling RSS and Atom. Unlike some other libraries it is pretty stable (18 months since the last release) and has a low number of dependencies (one &#8211; JDom &#8211; [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just pushed out a release of <a href="http://wiki.java.net/bin/view/Javawsxml/Rome">ROME</a> core, <a href="http://wiki.java.net/bin/view/Javawsxml/RomeFetcher">ROME Fetcher</a> and <a href="http://wiki.java.net/bin/view/Javawsxml/RomeModules">ROME modules</a>.</p>
<p>For those who don&#8217;t know, ROME is a (the?) Java library for handling RSS and Atom. Unlike some other libraries it is pretty stable (18 months since the last release) and has a low number of dependencies (one &#8211; JDom &#8211; if all you need is parsing)</p>
<p>The annoucement, including links is at <a href="https://rome.dev.java.net/servlets/ReadMsg?list=dev&amp;msgNo=2656">https://rome.dev.java.net/servlets/ReadMsg?list=dev&amp;msgNo=2656</a></p>
<p>The thing I&#8217;m most pleased about (and the number one source of complaints about ROME) is that I&#8217;ve pushed it to the java.net Maven repository, so now it will be easier to use from Maven. Further details are at <a href="http://wiki.java.net/bin/view/Javawsxml/RomeAndMaven2">http://wiki.java.net/bin/view/Javawsxml/RomeAndMaven2</a></p>
]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2009/01/08/rome-10rc2-release/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Installing Java on RedHat Linux by building your own RPM</title>
		<link>http://nicklothian.com/blog/2008/12/07/installing-java-on-redhat-linux-by-building-your-own-rpm/</link>
		<comments>http://nicklothian.com/blog/2008/12/07/installing-java-on-redhat-linux-by-building-your-own-rpm/#comments</comments>
		<pubDate>Mon, 08 Dec 2008 02:41:02 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=346</guid>
		<description><![CDATA[It&#8217;s pretty easy to install Java on Linux &#8211; download the RPM from sun and install it. Then if you run &#8220;java -version&#8221; you&#8217;ll suddenly discover that it doesn&#8217;t really work: java version "1.4.2" gij (GNU libgcj) version 4.1.2 20070626 (Red Hat 4.1.2-14) You can get around that by setting your path and JAVA_HOME, or [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s pretty easy to install Java on Linux &#8211; download the RPM from sun and install it. Then if you run &#8220;java -version&#8221; you&#8217;ll suddenly discover that it doesn&#8217;t really work:</p>
<pre>java version "1.4.2"
gij (GNU libgcj) version 4.1.2 20070626 (Red Hat 4.1.2-14)</pre>
<p>You can get around that by setting your path and JAVA_HOME, or by only using Java version that have a matching <a href="http://www.jpackage.org">JPackage </a>RPM and using the <em>alternatives</em> command</p>
<p>If you want to be able to build your own RPM, here&#8217;s how to do it.</p>
<p><em></em></p>
<p><em></em></p>
<p><em></em></p>
<p><em></em></p>
<p><em></em></p>
<p><em></p>
<ul>
<li><span style="font-style: normal;"><em>cat /etc/redhat-release</em> &#8211; this is tested on CentOS release 5 (Final). It should work elsewhere, but&#8230; yeah&#8230; good luck with that.</span></li>
<li><span style="font-style: normal;">Download the <strong>non-rpm</strong> Linux build from of java Sun. The filename will be something like jdk-6u11-linux-i586.bin. I&#8217;ve only tried this with the 32 bit build.</span></li>
<li><span style="font-style: normal;">Download the <em>jpackage17.repo</em> file from jpackage.org. Currently this is availabel from <a href="http://www.jpackage.org/cgi-bin/viewvc.cgi/website/htdocs/jpackage17.repo?revision=1.1&amp;root=jpackage&amp;view=markup">http://www.jpackage.org/cgi-bin/viewvc.cgi/website/htdocs/jpackage17.repo?revision=1.1&amp;root=jpackage&amp;view=markup</a> but the contents looks like this:</span></li>
</ul>
<p></em></p>
<p> </p>
<pre style="padding-left: 60px;"># Be sure to enable the distro specific repository for your distro below:
# - jpackage-fc for Fedora Core
# - jpackage-rhel for Red Hat Enterprise Linux and derivatives

[jpackage-generic]
name=JPackage (free), generic
mirrorlist=http://www.jpackage.org/mirrorlist.php?dist=generic&amp;type=free&amp;release=1.7
failovermethod=priority
gpgcheck=1
gpgkey=http://www.jpackage.org/jpackage.asc
enabled=1

[jpackage-fc]
name=JPackage (free) for Fedora Core $releasever
mirrorlist=http://www.jpackage.org/mirrorlist.php?dist=fedora-$releasever&amp;type=free&amp;release=1.7
failovermethod=priority
gpgcheck=1
gpgkey=http://www.jpackage.org/jpackage.asc
enabled=0

[jpackage-rhel]
name=JPackage (free) for Red Hat Enterprise Linux $releasever
mirrorlist=http://www.jpackage.org/mirrorlist.php?dist=rhel-$releasever&amp;type=free&amp;release=1.7
failovermethod=priority
gpgcheck=1
gpgkey=http://www.jpackage.org/jpackage.asc
enabled=0

[jpackage-generic-nonfree]
name=JPackage (non-free), generic
mirrorlist=http://www.jpackage.org/jpackage_generic_nonfree_1.7.txt
failovermethod=priority
gpgcheck=1
gpgkey=http://www.jpackage.org/jpackage.asc
enabled=1</pre>
<ul>
<li>Become root</li>
<li>Copy this file to /etc/yum.repos.d. Edit it, and make sure that <em>enabled=1 </em>is set for the <em>[jpackage-generic-nonfree]</em> section.</li>
<li>Make directories required by the RPM process (I suspect you can do this outside the /usr/src directory, though):  <em></em></li>
</ul>
<pre style="padding-left: 60px;">mkdir -p /usr/src/redhat/SOURCES  
mkdir -p /usr/src/redhat/RPMS/i586/</pre>
<ul>
<li>Copy the Java installation file you previously downloaded to <em>/usr/src/redhat/SOURCES </em>and make it executable (<em>chmod +x &lt;name of file&gt;</em>)</li>
<li>Install the tools you need to build an rpm: <em>yum install yum-utils jpackage-utils rpm-build  </em>(At the moment this seems to fail on 64bit machines because of missing dependencies)</li>
<li><em>cd usr/src/redhat/SOURCES</em></li>
<li><em>yumdownloader &#8211;source java-1.6.0-sun</em></li>
<li>At the moment, that will download a file called <em>java-1.6.0-sun-1.6.0.10-1jpp.nosrc.rpm</em></li>
<li>Run <em>setarch i586 rpmbuild &#8211;rebuild java-1.6.0-sun*nosrc.rpm.</em> At the moment that gives an error message, which seems to be able to be ignored:</li>
</ul>
<pre style="padding-left: 60px;">sh: /usr/src/redhat/SOURCES/jdk-6u10-linux-i586.bin: No such file or directory</pre>
<pre style="padding-left: 60px;">error: Bad exit status from /var/tmp/rpm-tmp.6041 (%prep)</pre>
<pre style="padding-left: 60px;">RPM build errors:</pre>
<pre style="padding-left: 60px;">    user jasonc does not exist - using root</pre>
<pre style="padding-left: 60px;">    group jasonc does not exist - using root</pre>
<pre style="padding-left: 60px;">    user jasonc does not exist - using root</pre>
<pre style="padding-left: 60px;">    group jasonc does not exist - using root</pre>
<pre style="padding-left: 60px;">    user jasonc does not exist - using root</pre>
<pre style="padding-left: 60px;">    group jasonc does not exist - using root</pre>
<pre style="padding-left: 60px;">    Bad exit status from /var/tmp/rpm-tmp.6041 (%prep)</pre>
<ul>
<li>That previous command extracted a RPM SPEC file in the <em>/usr/src/redhat/SPECS/</em> directory.</li>
</ul>
<ul>
<li>Edit <em>/usr/src/redhat/SPECS/java-1.6.0-sun.spec</em>. Find the part that says <em>%define buildver</em> and change the value to the build for the new version of Java</li>
<li>Run <em>rpmbuild -ba /usr/src/redhat/SPECS/java-1.6.0-sun.spec</em>. This extracts the JDK installer you previously downloaded and builds a set of RPMs from it.</li>
<li><em>cd /usr/src/redhat/RPMS/i586; ls;</em></li>
</ul>
<pre><em>
<div style="padding-left: 30px;"><span style="font-style: normal;">java-1.6.0-sun-1.6.0.11-1jpp.i586.rpm        java-1.6.0-sun-fonts-1.6.0.11-1jpp.i586.rpm</span></div>
<div style="padding-left: 30px;"><span style="font-style: normal;">java-1.6.0-sun-alsa-1.6.0.11-1jpp.i586.rpm   java-1.6.0-sun-jdbc-1.6.0.11-1jpp.i586.rpm</span></div>
<div style="padding-left: 30px;"><span style="font-style: normal;">java-1.6.0-sun-demo-1.6.0.11-1jpp.i586.rpm   java-1.6.0-sun-plugin-1.6.0.11-1jpp.i586.rpm</span></div>
<div style="padding-left: 30px;"><span style="font-style: normal;">java-1.6.0-sun-devel-1.6.0.11-1jpp.i586.rpm  java-1.6.0-sun-src-1.6.0.11-1jpp.i586.rpm</span></div>

</em></pre>
<ul>
<li>You can now install the RPM: <em>rpm -i java-1.6.0-sun-1.6.0.11-1jpp.i586.rpm</em></li>
<li>For me that failed with a missing X dependency: <em>libXtst.so.6 is needed by java-1.6.0-sun-1.6.0.11-1jpp.i586</em></li>
<li>I fixed that with <em>yum -y install libX11-devel libXtst.</em></li>
<li>Use the alternatives command to set the correct version of Java: <em>alternatives &#8211;config java</em></li>
<li>Finally: <em>java -version:</em></li>
</ul>
<pre><em>
<div style="padding-left: 30px;"><span style="font-style: normal;">java version "1.6.0_11"</span></div>
<div style="padding-left: 30px;"><span style="font-style: normal;">Java(TM) SE Runtime Environment (build 1.6.0_11-b03)</span></div>
<div style="padding-left: 30px;"><span style="font-style: normal;">Java HotSpot(TM) Client VM (build 11.0-b16, mixed mode, sharing)</span></div>

</em></pre>
<div><span style="font-style: normal;">That&#8217;s it &#8211; you finally have Java working on Linux! You also have a RPM which can be installed on other machines.</span></div>
]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2008/12/07/installing-java-on-redhat-linux-by-building-your-own-rpm/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Modify java.library.path at runtime</title>
		<link>http://nicklothian.com/blog/2008/11/19/modify-javalibrarypath-at-runtime/</link>
		<comments>http://nicklothian.com/blog/2008/11/19/modify-javalibrarypath-at-runtime/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 02:32:48 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=335</guid>
		<description><![CDATA[Linking to native code in Java is always a hassle. JNI isn&#8217;t exactly nice, and there are some oddities around classloaders and native libraries which are annoying if you run into them. One thing I wasn&#8217;t aware of was exactly how hard it is to load a library it isn&#8217;t already in the directories specified [...]]]></description>
			<content:encoded><![CDATA[<p>Linking to native code in Java is always a hassle. JNI isn&#8217;t exactly nice, and there are some oddities around classloaders and native libraries which are annoying if you run into them.</p>
<p>One thing I wasn&#8217;t aware of was exactly how hard it is to load a library it isn&#8217;t already in the directories specified by the java.library.path system property. </p>
<p>Initially, I thought I&#8217;d just be able to alter that property and the JVM would pick up the new locations. That turns out not to be the case, as is shown by <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4280189">this (closed) bug report</a>.</p>
<p>However, there is a solution, outlined in <a href="http://forums.sun.com/thread.jspa?threadID=707176">this post on the Sun forums</a>, which revolves around altering the <em>usr_paths</em> field stored in java classes.</p>
<pre>	public static void addDir(String s) throws IOException {
		try {
			// This enables the java.library.path to be modified at runtime
			// From a Sun engineer at http://forums.sun.com/thread.jspa?threadID=707176
			//
			Field field = ClassLoader.class.getDeclaredField("usr_paths");
			field.setAccessible(true);
			String[] paths = (String[])field.get(null);
			for (int i = 0; i &lt; paths.length; i++) {
				if (s.equals(paths[i])) {
					return;
				}
			}
			String[] tmp = new String[paths.length+1];
			System.arraycopy(paths,0,tmp,0,paths.length);
			tmp[paths.length] = s;
			field.set(null,tmp);
			System.setProperty("java.library.path", System.getProperty("java.library.path") + File.pathSeparator + s);
		} catch (IllegalAccessException e) {
			throw new IOException("Failed to get permissions to set library path");
		} catch (NoSuchFieldException e) {
			throw new IOException("Failed to get field handle to set library path");
		}
	}</pre>
<p>Obviously, I don&#8217;t think that&#8217;s portable across JVMs, though.</p>
]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2008/11/19/modify-javalibrarypath-at-runtime/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The problem with OpenID is&#8230;</title>
		<link>http://nicklothian.com/blog/2008/04/22/the-problem-with-openid-is/</link>
		<comments>http://nicklothian.com/blog/2008/04/22/the-problem-with-openid-is/#comments</comments>
		<pubDate>Tue, 22 Apr 2008 11:24:43 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[social networks]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[identity]]></category>
		<category><![CDATA[openid]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/?p=316</guid>
		<description><![CDATA[The problem with OpenID is branding &#8211; people get (very) confused when they get taken off site to login. I&#8217;ve watched usability testing of this, and it is truly horrible. Obviously this isn&#8217;t unique to OpenID &#8211; it applies equally to any federated identity solution (in fact &#8211; Shibboleth based federations are even worse than [...]]]></description>
			<content:encoded><![CDATA[<p>The problem with OpenID is branding &#8211; people get (very) confused when they get taken off site to login. I&#8217;ve watched usability testing of this, and it is truly horrible. Obviously this isn&#8217;t unique to OpenID &#8211; it applies equally to any federated identity solution (in fact &#8211; Shibboleth based federations are even worse than OpenID in this respect).</p>
<p>I think user education will help, but it would be really good to be able to extend OpenID to be able to put a logo on the identity provider&#8217;s site so the user can see they are logging into site &#8220;blah&#8221; via whatever open id provider.</p>
]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2008/04/22/the-problem-with-openid-is/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why tech predictions are stupid (and a small prediction)</title>
		<link>http://nicklothian.com/blog/2008/03/13/why-tech-predictions-are-stupid-and-a-small-prediction/</link>
		<comments>http://nicklothian.com/blog/2008/03/13/why-tech-predictions-are-stupid-and-a-small-prediction/#comments</comments>
		<pubDate>Thu, 13 Mar 2008 22:13:57 +0000</pubDate>
		<dc:creator>Nick Lothian</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[predictions]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://nicklothian.com/blog/2008/03/13/why-tech-predictions-are-stupid-and-a-small-prediction/</guid>
		<description><![CDATA[Every year hundreds of tech pundits go and make their predictions for the year &#8211; a trend I&#8217;m not immune to either. Alan Kay explained the problem with this the best: &#8220;The best way to predict the future is to invent it&#8221;. In a field like computing it is so easy for a single person [...]]]></description>
			<content:encoded><![CDATA[<p>Every year hundreds of tech pundits go and make their predictions for the year &#8211; a trend <a href="http://nicklothian.com/blog/2008/01/01/predictions-for-2008/">I&#8217;m not immune to either</a>. Alan Kay explained the problem with this the best: &#8220;The best way to predict the future is to invent it&#8221;. In a field like computing it is so easy for a single person to build something new it makes trying to make predictions a pointless <a href="http://www.willbeta.com/lose-weight-exercise/"><span style="display:none;">Lose Weight </span>Exercise</a>.</p>
<p>None the less, here&#8217;s something that is less of a prediction and more an <a href="http://www.willbeta.com/lose-weight-exercise/"><span style="display:none;">Lose Weight </span>Exercise</a> in deduction and rumor mongering. <strong>Sun is planning to launch a direct competitor to Amazon&#8217;s EC2 in the near future</strong> (not sure when exactly, but 2008 for sure). Note that this is different to the existing <a href="http://www.sun.com/service/sungrid/index.jsp">Sun Grid</a> product (which will presumably continue).</p>
]]></content:encoded>
			<wfw:commentRss>http://nicklothian.com/blog/2008/03/13/why-tech-predictions-are-stupid-and-a-small-prediction/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 1328439129.747 seconds -->

