Sunday, 28 December 2008

Scala, Ant

An example of building Scala applications using Ant and the Scala Ant tasks:

In the complete Ant build file given below, the key lines are:


<taskdef resource="scala/tools/ant/antlib.xml">
<classpath>
<pathelement location="${scala.home}/lib/scala-compiler.jar" />
<pathelement location="${scala-library.jar}" />
</classpath>
</taskdef>
Which loads the task definition

scala-library.jar defines Scala tasks for Ant, these are:
  • scalac
  • fsc
  • scaladoc

Note: The Scala library scala-library.jar must be present in the Java class path. The actors and dbc libraries are available as separate JAR files: scala-actors.jarand scala-dbc.jar.


Example build.xml

// LJB 28-12-2008 - basic scala Ant build
<project name="Scala test" default="build" basedir="../">

<property name="base.dir" value="${basedir}" />
<property name="sources.dir" value="${base.dir}/src" />
<property name="build.dir" value="${base.dir}/build//classes.tmp" />

// take scala ant libs from scala installation, assumes SCALA_HOME is set to home of scala in env vars
<property environment="env"/>
<property name="scala.home" value="${env.SCALA_HOME}" />

<target name="init">

<property name="scala-library.jar" value="${scala.home}/lib/scala-library.jar" />

<path id="build.classpath">
<pathelement location="${scala-library.jar}" />
<!--<pathelement location="${your.path}" />-->
<pathelement location="${build.dir}" />
</path>

<taskdef resource="scala/tools/ant/antlib.xml">
<classpath>
<pathelement location="${scala.home}/lib/scala-compiler.jar" />
<pathelement location="${scala-library.jar}" />
</classpath>
</taskdef>
</target>

<target name="build" depends="init">

<mkdir dir="${build.dir}" />

<scalac srcdir="${sources.dir}"
destdir="${build.dir}"
classpathref="build.classpath"
force="changed">

<!-- <src location="src" /> -->
<include name="**/*.scala" />
</scalac>
</target>

<target name="run" depends="build">
<java classname="test.Test"
classpathref="build.classpath">
</java>
</target>
</project>




Project directory structure:

/build
/build/build.xml
/src
/src/test.scala


Example "hello world" Scala test program


package test

object Test {

def main(args : Array[String]) {

println("Hello world")
}
}


If you type ant run in the /build directory, the application is compiled and run, giving "Hello world"...


References:

http://www.scala-lang.org/node/98


.

Saturday, 27 December 2008

Scala - object, singletons, classes and constructors

Today, a simple example by way of explanation of the basic constructs of OO in Scala.

Things to note:
  • Scala does not use static methods, in this sense Scala is more purely OO than Java.
  • The equivalent is achieved using object singletons and companion objects.

The following code example demonstrates:

  • Use of object singleton and "main" application entry point
  • Declaration of new objects
  • Declaration of new class
  • Class primary constructor
  • Declaring fields
  • Declaring alternative constructors
  • Use of override keyword

Example Code:

package test

// object declares a singleton (like Java static)
object Test {
// the usual main, takes an Array[String] of arguments
def main(args : Array[String]) {

var myClass1 = new MyClass(5, "Louis") // using primary constructor
var myClass2 = new MyClass(10); // using alternate constructor

// access public field value
println("myClass1.value1 = " + myClass1.value1)

// output using overriden toString
println("myClass1 = " + myClass1)
println("myClass2 = " + myClass2)
}
}

// define MyClass and its primary constructor (Int, String)
class MyClass(v1 : Int, s1 : String) {

// these are fields (public)
def value1 : Int = v1
def string1 : String = s1

// this is an alternate constructor (calls primary constructor)
def this(v1 : Int) = {
this(v1, "hello")
}

// can override toString like in Java, note no return statement required + the override keyword
override def toString() : String =
{
"MyClass: (" + value1 + ", " + string1 + ")"
}
}

Wednesday, 24 December 2008

Scala, an introduction

Scala - "Scalable Java": a new Language which combines both Object Orientated and Functional programming paradigms.

Scala is an extension of Java and runs on the JVM. Scala draws from languages such as Java, Smalltalk, Erlang and many others.

Scala site: http://www.scala-lang.org/

Downloads: http://www.scala-lang.org/downloads

Installation, using the IzPack Scala installer jar, run: java -jar scala-x-installer.jar


Scala - main features:
  • Integrates with Java (is an extension of Java), and shares libraries and primitive types
  • Compiles to Java byte code - runs on JVM (also can be run on .Net)
  • Imperative and functional support
  • Object Orientated (classes, objects)
  • Functional (functions as first class objects, referential transparency)
  • Statically typed
  • Type inference (more concise code that looks more like Dynamic/duck typed, but has the benefits of static / strong typing)
  • Supports closures and function literals
  • Concurrency model using Erlang Actors system (a 'safer' concurrency model)
Scala can be run stand alone, using the command line interpreter - using the "scala" command.

Scala also has plugin support for NetBeans, Eclipse and InteliJ


Syntax Overview:
  • Type inference means most type declarations can be omitted (but can still be explicitly declared).
  • Variables are defined as name : type rather than type name as per Java
  • Semicolons are often optional
  • Does not specify or define operators. +-*/ etc are valid method names are defined as such for appropriate types
  • var and val keywords - val declares a constant type (like Java's final, not reassignable), var declares a variable that can be reassigned. val, like var can still be mutable however, if the type is mutable.
  • Functions, declared using def keyword. e.g. def myFunction(x: Type1, y: Type2) : ReturnType
  • Pre and post increment/decrement (i++, ++i, i--, --i) are not supported, use i = i + 1 or i += 1
  • Recommended indentation is 2 spaces
  • Imperative for loops not supported, the functional equivalent, a for Expression is used instead
  • Arryays are indexed using (n) not [n]
  • Type parameters are specified using [type]. If both type and index are used, the ordering is [type](params)
  • Scala supports infix as method calls. e.g. 1 + 2 is equivalent to 1.+(2) where + is not a special operator, but a regular method
  • Applying () to an object (recipient) is equivalent to calling .apply() on it. e.g. myThing(i) is equivalent to myThing.apply(i)
  • The receiver of an = operator is equivalent to calling .update. e.g. myThing(i) = value is equivalent to myThing.update(i, value)
  • Method association is by default to the left, unless the method ends with a colon : e.g. 1 + 2 applies + to 1 giving 1.+(2) whereas x :: y applies :: (cons) to y, giving y.::(x)
  • The List type supports ::: (concat) and :: (cons, prepend), both apply the operation and return the resulting new List
  • Arrays are always mutable, lists are always immutable. Sets and maps can be either, the default is immutable (from the trait scala.collection.immutable) but the mutable equivalents can be imported from scala.collection.mutable
  • The -> method provides Implicit Conversion. e.g. x -> y is x.->y which returns a key/value tuple containing x as the key and y as the value

Some simple Functional examples:

Print all command line arguments, using foreach, passing println function:

Verbose:
args.foreach((arg: String) => println(arg))

Type inference on arg:
args.foreach(arg => pringln(arg))

Concise:
args.foreach(println)

The last example is a shorthand that can be applied when a function literal cosists of one statement that takes one argument - known as a Partially Applied Function.


For Expressions:

Replacing imperative for loops, the syntax is of the form:

for (arg <- args)
println(arg)


Note: In the above for expression example, arg is a val (final/const) not a var, and a new val variable is created for each "iteration".

or

for (i <- 1 to 30) ...


Declaring Arrays:

Very concisely:

val myArray = Array("value1", "value2")

defines a string array (type inference) of size 2

This is equivalent to:

val myArray = Array.apply("value1", "value2")

where apply is called on the Array Companion Object

More Verbosely the array could also be declared more traditionally as:

val myArray = new Array[String](2)

or even

val myArray : Array[String] = new Array[String](2)

but the former concise approach is the Scala recommended way, the later hints at the underlying Java roots.

Lists:

Defining new lists is easy with the cons method, as follows:

val myList = 3 :: 2 :: 4 :: 5 :: Nil // Nil is the Empty List, also so is List()

Note: The Nil (empty List) is needed so that working from right to left, the :: method is defined on Nil, which first gives Nil.::(5) returning List(5) which then gives 5.::(4) resulting in List(4, 5), and so on. Without the Nil there is a syntax error as :: (cons) is not defined on 5 (which is of type integer).


Examples:

Factorial ! - Simple factorial, defined in a functional way:

def factorial(value : int) : int = { if (value == 0) 1 else value * factorial(value - 1) }

scala> factorial(10)
res15: int = 3628800


Triangle Numbers:

def tri(x : Int) : Int = { if (x == 0) 0 else x + tri(x-1) }

scala> tri(4)
res14: Int = 10


Scala for scripting:

Scala scripts can be run using scala myscript.scala

Additionally, Scala can be used as a self contained scripting language by invoking the scala command line interpreter with the script, as follows:

On 'nix platforms

#!/bin/sh
exec scala "$0" "$@"
!#
println("Hello world, hello " + args(0))

Don't forget to give the script execute permissions (chmod +x myscipt)

Execute: myscript Louis

A similar thing can be achieved on Windows...


Scala with build systems:


With Ant:

http://www.scala-lang.org/node/98


With Maven:

http://scala-blogs.org/2008/01/maven-for-scala.html


Further Resources:

Books:

Artima book (excellent): http://www.artima.com/shop/programming_in_scala released 17th Nov 2008, by Martin Odersky, Lex Spoon, and Bill Venners.

Source code for book examples: http://booksites.artima.com/programming_in_scala/progInScalaExamples1EdV6.zip

Browse book examples: http://booksites.artima.com/programming_in_scala/examples

OReilly Programming Scala: http://programming-scala.labs.oreilly.com/


Blogs:

http://www.scala-blogs.org/

Blog on Monads: http://james-iry.blogspot.com/2007/09/monads-are-elephants-part-1.html


Articles:

Java refugees: http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-1


Build tools:

SBT: http://code.google.com/p/simple-build-tool/


Interesting Blog about Scala and Lift (using Maven and Jetty).

http://scala-blogs.org/2007/12/dynamic-web-applications-with-lift-and.html


SIDs (software improvement Documents):

http://www.scala-lang.org/sids


Monads:

http://projects.tmorris.net/public/what-does-monad-mean/artifacts/1.1/chunk-html/ar01s04s04.html

http://vimeo.com/8729673


IRC channel: #scala on irc.freenode.net


(Also (unrelated): pastie - http://pastie.org/ is handy for pasting those odd snippets of code around on the internet/IRC).


Interesting blog about Scala type-safe SQL / DB - SQuery - http://szeiger.de/blog/2008/12/21/a-type-safe-database-query-dsl-for-scala/

Updated (13-09-2009): Came across this useful presentation: http://www.slideshare.net/astubbs/scala-language-intro-inspired-by-the-love-game?src=embed


99 Scala problems - an adaption of the 99 Prolog problems into Scala:

http://aperiodic.net/phil/scala/s-99/#p10


.

Sunday, 21 December 2008

PCWiz Mac OSX under VMware (2.0)

(Note - I do not condone the use of illegal / pirated software. If you're going to use Mac OSX, please support Applet and buy a license for the OS.)


Mac OSX can be run under VMware, using a special build such as the "pcwiz" version.

http://pcwizcomputer.com/index.php?Itemid=48&id=76&option=com_content&task=view
  • Performance is slow, but just about usable.
  • There's naturally no vmware tools at this time.
  • Networking can be made to work.
When it comes to the screen resolution, there are no drivers as such to adjust but the screen resolution settings can be modified - see here for further details: http://pcwizcomputer.com/index.php?option=com_content&task=view&id=31&Itemid=45


.

Saturday, 13 December 2008

OpenOffice (3.0) / UNO API

Recently a project needed some reporting enhancements (spreadsheet charts) for which Apache POI didn't provide the necessary support. So, after some exploration, I decided on using OpenOffice with it's API, in this particular instance it was OpenOffice 3.0m9 (latest at the tine of writing) and the UNO Java API.

www.openoffice.org

OpenOffice provides some very powerful tools, including Spreadsheets, Documents, PDF etc along compatibility with MS Office. In addition, OpenOffice is quite powerful at convertion document types and between versions. For example a MS word document could be loaded and then saved as a PDF.

OpenOffice - www.openoffice.org
Forum - http://user.services.openoffice.org/en/forum/
Wiki - http://wiki.services.openoffice.org/wiki/Main_Page (including good developer section)
FAQ - http://wiki.services.openoffice.org/wiki/Uno/FAQ

The OpenOffice suite comes with an SDK and the UNO API, supporting various languages, including Java.

SDK download - http://download.openoffice.org/3.0.0/sdk.html

The SDK/API is based on UNO (Unified Network Objects) which is an alternative/competator to COM, like CORBA etc, and allows the remote (out of process) communication and control of OpenOffice - "UNO is a component model that offers inter-operability between different programming languages, different objects models, different machine architectures, and different processes; either in a LAN or via the Internet."

Another acronym is URE - "Each component lives in a Uno Runtime Environment (URE). A URE is identified by the implementation language (e.g., C++, Java, Perl, ...) and the current process."

See here for more details: http://udk.openoffice.org/common/man/uno.html

When using OpenOffice on the server side to provide reports (in my case, as part of a web application), various SDK jars are needed along with a means to find the OpenOffice installation.

The Java jars needed are:
  • juh.jar
  • jurt.jar
  • ridl.jar
  • jut.jar
  • unoil.jar

I chose to include them in my web application WAR file.
This can create problems, because the classpath to the jars will not be where OpenOffice is installed, to work around this the Java classes from the SDK can be loaded and bootstrapped in the class loaded, but this is tricky when using a web app container. For convienience I made use of the useful bootstrapconnector.jar utility library. This library can connect to OpenOffice regardless of the location of the jars, it just needs a path to an OpenOffice installation, which I set as an ENV variable called UNO_PATH.

BootstrapSocketConnector - http://user.services.openoffice.org/en/forum/viewtopic.php?f=44&t=2520

I also made use of the OpenOffice plugin for Netbeans 6.5 to get a quick start developing the code, before moving to the production solution.


Some things to watch out for:

One problem I stumbled into. Installing OpenOffice for the first time on a remote Linux (CentOS) machine over a terminal, when I came to run the web application the program appears to hang. Some investigation with ps showed that soffice was being started, but that I was getting many instances, all apparently hung. I replicated the setup on a different Linux installation, this time one with a desktop / display manager. It was then obvious what was happening, the first time OpenOffice is launched, it prompts the user with a registration wizard! Oops.

So the solution to this is simple, pass an option when launching the OpenOffice process, this can be achieved conveniently using the bootstrapsocketconnect with something like the following:

// Create OOo server with additional -nofirststartwizard option
List oooOptions = OOoServer.getDefaultOOoOptions();
oooOptions.add("-nofirststartwizard");
OOoServer oooServer = new OOoServer(OOO_EXEC_FOLDER, oooOptions);

// Connect to OOo
BootstrapSocketConnector bootstrapSocketConnector = new BootstrapSocketConnector(oooServer);
XComponentContext remoteContext = bootstrapSocketConnector.connect();


.

Sunday, 7 December 2008

JSON, Java and JavaScript

JSON is so simple there's not a lot to say about it, but I thought it's worth putting up a few links and notes for reference.

JSON is JavaScript Object Notation. Whilst it could be called an Object Notation (a simple one), it's not tied to JavaScript, although it's early origins are from that language (ECMAScript, ECMA-262 3rd Edition). JSON is essentially language independant, like XML. JSON, like XML can represent data structures and data (self describing) but unlike XML, JSON does not support namespaces, schema and other more advanced features. JSONs key strengths are its simpicity and low overhead, terse message size.


JSON looks like this:


{
"firstName": "John",
"lastName": "Smith",
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": 10021
},
"phoneNumbers": [
"212 555-1234",
"646 555-4567"
]
}


Where { and } contain the object, the properties are listed as "name" : "value" pairs. Objects can be embedded within objects and arrays are denoted using comma separated lists within []

So, special symbols (for escaping) are: {}[]:"

Main Site: http://www.json.org/

Simple JSON for Java: http://www.JSON.org/java/json_simple.zip http://www.json.org/java/simple.txt

Simple JSON for JavaScript: http://www.json.org/js.html

Wikipedia: http://en.wikipedia.org/wiki/JSON


JavaScript:

Basic suppport for converting JSON messages into objects (deserialisation) is to use the often best avoided eval function, as follows:

var myObject = eval('(' + myJSONtext + ')');

where the outer '(' ')' are necessary for the JavaScript language, not JSON itself.

Better (safer) still, various libaries are available, such as the Open Source version from www.json.org in json2.js

Which essentially is used like this:

var myObject = JSON.parse(myJSONtext, reviver);

var myJSONText = JSON.stringify(myObject, replacer);


Java:

Create a JSON string using org.json.simple.JSONObject:

JSONObject obj=new JSONObject();
obj.put("name","foo");
obj.put("num",new Integer(100));
System.out.print(obj);

The toString() on the JSONObject serialises the JSON object (map of name value pairs) to a JSON string.

JSON is simple, by design, so there isn't much more to be said on it.

One of the main things to watch out for is encoding/escaping messages so they are JSON friendly, I'll add more on that soon.

The following link may be useful when working with character escaping: http://www.the-art-of-web.com/javascript/escape/

.

Sunday, 23 November 2008

BIOS LBA / Hard disk, apparent failure problem "Blinking cursor of doom"

A rather interesting low level problem: If you ever get a machine inexplicably stuck after POST with a blinking cursor in the top right and nothing more and want to know why or fix it, please read on!

Whilst there are a number of possible causes (like incorrect BIOS settings) I'm assuming all of those have been checked and ruled out, if so and the problem still persists then the following might be an explanation:

A while back I upgraded my ageing Dell Ispiron 6000 laptop hard drive (80gb) with a 160gb drive. I cloned the original drive to retain everything but made the partition larger to make the extra space available. The machine ran XP Pro SP2 and had been stable for a couple of years, since I first got it (after a battle with a nasty virus that I evenually managed to win a few months previously).

An easy enough job and all was good, for a while. One day the machine needed a reboot, after shutting down it came back with the Blinking cursor of Doom!

This is where, straight after POST (Power On Self Test) the machine totally hangs (before Windows starts up). My first thoughts (after oh crap) where along the lines of, has the drive died, mbr gone wrong, virus trashed the drive, partition table messed up, file system corrupt etc?

After many hours, I'd done a full chkdsk /r, fixmbr, checked the MBR (Master Boot Record) and Partition Table information, made sure the partition was active and so on, I even moved and resized the partition slightly, swapped the drive into another machine (was fine), tried a different drive in the laptop, also fine. Checked my BIOS (Basic Input Output System) for updates and so on - nothing seemed to be wrong - weird!

The MBR is the sector at cylinder 0, head 0, sector 1 - it's launched according to the BIOS boot sequence, if the BIOS finds a valid MBR it's copied to memory and executed as part of the boot sequence of the machine.

I also looked and the Windows MBR code (disassembly) from here http://mirror.href.com/thestarman/asm/mbr/STDMBR.htm to check all paths through the boot loader - all likely paths result in a message of some sort like the archaic "Please insert boot disk" type messages. I just got a blank screen with flashing cursor - how come?

I could see all the files on the disk, the disk and it's contents appears fine - so the question was what on earth was stopping the disk from being bootable!?. It defied any logic, surely if the file system is intact, has no errors, the partition table was fine and everything was set for the system to boot from it, why didn't it?

After much time was spent on it (I really didn't want to have to set everything up again) eventually I decided it would be quicker to re-ghost from the original 80gb drive and get back to where I was 2 or 3 months previously, then copying over any new data from the fine but un-bootable 160gb drive.

I did this and all was well again (but in the back of my mind I was never happy I'd not managed to get to the bottom of it).

My machine was working but I was puzzled. The machine starts up in the System BIOS, it runs various checks and initialises the hardware and subsystems before trying to find a bootable volume. Assuming a bootable hard disk is found, the MBR is executed, the partiton tables are examined and active partition is bootstrapped, the first "file" lauched in a windows 2000/XP/NT platform being the ntldr program responsible for starting windows (and capable of multiboot).

Whilst dissatisfied I'd not understood the problem, as days and weeks passed, the problem faded into a dim and distant memory...


--


Then, about 3 - 4 months later - after updating ITunes and needed to reboot, the same thing stuck again! Now this time, whilst rather disappointed, I knew there had to be an explanation. Maybe it was hardware related, maybe the machine was unreliable - how could I trust it again if it did this every so often?

So, this time around I thought I need to get to the bottom of this - there must be a reason, it's happened twice in a row, and suspiciously in roughly similar time spans (3 months or so) from the original disk clone - this had to be a clue.

So, after chkdsk /r etc just to check everything was ok, I got to work.

The disk was un-bootable, but the file system was fine. It hung immediately after POST, but with the briefest of flashes of the hard disk light. This had to be something low level, before windows, after POST - not much happens, especially knowing the MBR and partition tables were intact and fine too.

I renamed c:\ ntldr, IO.SYS and NTDETECT.COM, the low level bootstrap files for Windows.

After booting, the machine did exactly the same. Ahah this was a clue of sorts, if the disk was bootable but it wasn't getting as far as running ntldr then the fault was prior to that. If MBR and partition table were ok, then the fault was prior to that also, so, the BIOS?

I checked again for BIOS updates, nothing released matched the problem.

Then, after much Googling came the clue. Some BIOSes have an intrinsic 137gb limit.

That's 137gb of addressable disk, which might translate to less taking into account the overhead of the file system and block sizes etc.

Whilst Windows is happy to grow the file system behond this limit, eventually the BIOS will reach this maximum and barf. So, it could explain it....

There was only one way to find out. I resized the partition (made smaller) and created a new one in the new spare space. I copied files over from the original partition and then resized it smaller again, growing the new one until they were about the same size (2 x 80gb partitions rather than 1 x 160gb).

I restart with the downsized partition this time the machine comes up with a more helpful missing ntldr error message - ahah! it's tried to boot from the disk!

Booting up for a final time from the boot disk I renamed the files (ntldr etc) back. Reboot one last time and hey presto, it's working fine. Nothing lost, and this time I only lost a few hours (3 or 4) from my life and most importantly, I got some closure on the problem and an understanding of what happened and how to avoid it forever.

Greatly satisfied and relieve, I thought I'd share this experience in case it helps someone else in a similar position. Like anything, when you know the answer it's easy, but I've worked with computers for years and for a while there I was completely stumped with a problem that seemed, rather un-computer like, to defy all logic!

Whilst I'm entirely happy with two smaller partitions, the longer term solution is known as 48bit LBA, AKA Big LBA - http://en.wikipedia.org/wiki/Advanced_Technology_Attachment


References:

http://en.wikipedia.org/wiki/Master_boot_record
http://en.wikipedia.org/wiki/Booting#Boot_loader
http://en.wikipedia.org/wiki/Windows_NT_Startup_Process

http://mirror.href.com/thestarman/asm/mbr/STDMBR.htm
http://www.ata-atapi.com/hiwmbr.html

http://en.wikipedia.org/wiki/Advanced_Technology_Attachment

.

Applet <-> Javascript integration

It's been a while since I've done this, but I thought I'd refresh my memory on the options available. Maybe Applets have fallen out of favour a bit and whilst Javascript is popular for Rich, Dynamic Internet Applications, sometimes you need more and one way to do it is to use Applets, or integrate Applets with Javascript.

This example shows some simple ways to achieve Applet/JavaScript integration:

I've included example HTML with JavaScript source and Java source code for an Applet, to demonstrate so ways to achieve JavaScript to Java Applet integration. The simple example code demonstrates both JavaScript calling a Java Applet and a Java Applet calling JavaScript.

The JavaScript function jsShowMsg(String) is called in two different ways from the Java Applet. A single string parameter is passed, and the JavaScript function displays this using the standard alert() function to create a dialog box.

The Applet provides a showMessage(String) public method, which similarly is called by the JavaScript code when the button on the page is pressed. The String parameter is taken from the text field and displayed in the Applet.

HTML Page:


Provides the Applet on the page. Provides the JavaScript function called by the Applet, calls the Applet public method when the button is clicked (takes the String value from the input text box.

--

<HTML>
<HEAD>
<TITLE>Applet HTML Page</TITLE>
</HEAD>
<BODY>
<script type="text/javascript">

/**
* jsShowMsg - demostrates being called by an Applet, being passed a single String argument, the message
*/
function jsShowMsg(msg)
{
alert("Message from applet was: '" + msg + "'");
}

/**
* callApplet - demonstrates calling a public method on the Applet (showMessage(String))
*/
function callApplet(msg)
{
//alert("before calling Applet method with msg=" + msg);

document.testApplet.showMessage(msg);

//alert("after calling Applet method");
}
</script>

<H3><HR WIDTH="100%">Applet HTML Page - Applet <-> JavaScript integration example<HR WIDTH="100%"></H3>

<P>
<APPLET name="testApplet" codebase="classes" code="com/chillipower/TestApplet.class" width=400 height=150></APPLET>
</P>

<input type="text" id="msgTb" name="msgTb" value="A message from JS!" /><input type="button" value="button1" onclick="callApplet(getElementById('msgTb').value);" />

</BODY>
</HTML>

--


Java Applet Class:


Calls the JavaScript function in two different ways when the Applet is started. Provides a showMessage public method that the JavaScript can call.

--

package com.chillipower;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;

/**
* @author Louis B
*/
public class TestApplet extends Applet
{
String JS_MESSAGE = "Hello from Java Applet to JavaScript (using JavaScript alert)";
String JS_FUNC_NAME = "jsShowMsg";


/**
* init - applet init function
*/
@Override
public void init()
{
setBackground(new Color(0xFAFAFF));
}

/**
* start - applet start function
*/
@Override
public void start()
{
callJsByProto(JS_FUNC_NAME, JS_MESSAGE + " using showDocument :javascript protocol method");

callJsFunc(JS_FUNC_NAME, JS_MESSAGE + " using JSObject method");
}

/**
* Overide paint with simple text rendering
*
* @param g
*/
@Override
public void paint(Graphics g)
{
g.drawString("The Applet", 20, 20);
}

/**
* Simple function to show a message
*
* @param msg
*/
public void showMessage(String msg)
{
Graphics g = getGraphics();
g.setColor(Color.RED);
g.drawString("Message from JS: '" + msg + "'", 20, 40);
}

/**
* Call a named JS function, passing a single String parameter
*
* @param funcName
* @param msg
*/
private void callJsByProto(String funcName, String msg)
{
try
{
getAppletContext().showDocument
(new URL("javascript:" + funcName + "(\"" + msg +"\")"));
}
catch (MalformedURLException ex)
{
System.out.println("ex: " + ex.getMessage());
}
}

/**
* callJsFunc - call the named JavaScript function, passing the String msg argument
*
* @param funcName
* @param msg
*/
private void callJsFunc(String funcName, String msg)
{
String jscmd = funcName + "('" + msg + "')"; // Buiild the JavaScript command
String jsresult = null;
boolean success = false;

try
{
Method getw = null;
Method eval = null;
Object jswin = null;
Class c = Class.forName("netscape.javascript.JSObject"); /* works in IE too */
Method ms[] = c.getMethods();

for (int i = 0; i < ms.length; i++)
{
if (ms[i].getName().compareTo("getWindow") == 0)
{
getw = ms[i];
}
else if (ms[i].getName().compareTo("eval") == 0)
{
eval = ms[i];
}
}

Object a[] = new Object[1];
a[0] = this; /* this is the applet */
jswin = getw.invoke(c, a); /* this yields the JSObject */
a[0] = jscmd;
Object result = eval.invoke(jswin, a);

if (result instanceof String)
{
jsresult = (String)result;
}
else
{
jsresult = result.toString();
success = true;
}
}
catch (InvocationTargetException e)
{
jsresult = e.getTargetException().getMessage();
}
catch (Exception e)
{
jsresult = e.getMessage();
}

if (success)
{
System.out.println("JS eval succeeded, result is " + jsresult);
}
else
{
System.out.println("JS eval failed with error " + jsresult);
}
}
}

Debugging:

1. Using the Java ControlPanel (on 'nix, it is View Settings -> Edit the Java Runtime settings.

-agentlib:jdwp=transport=dt_socket,address=:

This makes the browser plug-in JRE open a debugging socket connection when launching the applet.

2. Open the Netneans project and attach the debugger in the SocketListen mode, using the same settings as above.



Resources:

http://windyroad.org/2006/08/14/reintroducing-javascript-and-hidden-applets-jaha/

http://java.sun.com/javase/6/docs/technotes/guides/plugin/developer_guide/java_js.html


.

Sunday, 16 November 2008

Apache httpd 2.x -> Glassfish 2.x mod_jk installation


Configure Apache Httpd to Glassfish using mod_jk.


Note
, for Glassfish 3.x this process has been simplified, I'll probably add a blog entry about that sometime soon.

In this particular scenario, Apache 2.2.3 is running on Centos 5.2 x86_64 and Glassfish 2ur2 is running on OpenSolaris 10 b101, althought the process should be essentiually the same for any Operating system(s), the paths etc might change.


Apache httpd setup:


Get the Apache mod_jk connector.

http://tomcat.apache.org/connectors-doc/

Binary distribution:

http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/

Install into modules directory: e.g. /etc/httpd/modules (RH/Centos)

Configure Apache httpd:

e.g. for RH/Centos in - /etc/httpd/conf.d/

Add ajp worker mapping to httpd.conf (e.g. in /etc/httpd/conf/), in this example using virtual host entries, e.g.



# Virtual host chillipower.com
[VirtualHost 192.168.0.200]

DocumentRoot /var/www/mywebs/chillipower.com

ServerName www.chillipower.com

ServerAlias chillipower.com

DirectoryIndex index.html index.php index.htm index.shtml

JkMount /chillipower*/* worker1

[/VirtualHost]



Note in the above, the url to the glassfish context would be reached using http://mydomain.com/chillipower/ where in this instance the trailing / is important.

Load and configure the module (e.g. place this in /etc/httpd/conf.d/mod_jk.conf)

(all *.conf files are loaded by httpd.conf (before any virtual hosts etc) from the /conf.d directory in typical setups, so we can add a new mod_jk.conf and it will be loaded automatically)


LoadModule jk_module /etc/httpd/modules/mod_jk.so
JkWorkersFile /etc/httpd/conf.d/worker.properties
# Where to put jk logs
JkLogFile /var/log/httpd/mod_jk.log
# Set the jk log level [debug/error/info]
JkLogLevel debug
# Select the log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
# JkOptions indicate to send SSL KEY SIZE,
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
# JkRequestLogFormat set the request format
JkRequestLogFormat "%w %V %T"
# Send all jsp requests to GlassFish
JkMount /*.jsp worker1
# Send all glassfish-test requests to GlassFish
JkMount /chillipower/* worker1



Add worker.properties file to configure the ajp worker, /etc/httpd/conf.d/worker.properties




# Define 1 real worker using ajp13
worker.list=worker1
# Set properties for worker1 (ajp13)
worker.worker1.type=ajp13
#worker.worker1.host=localhost.localdomain
worker.worker1.host=192.168.3.101
worker.worker1.port=8009
worker.worker1.lbfactor=50
worker.worker1.cachesize=10
worker.worker1.cache_timeout=600
worker.worker1.socket_keepalive=1
worker.worker1.socket_timeout=300




Glashfish setup:

Download Apace Tomcat 5.5.16 -> http://archive.apache.org/dist/tomcat/tomcat-5/

copy the tomcat-ajp.jar to the glassfish lib folder. e.g.

cp $CATALINA_HOME/server/lib/tomcat-ajp.jar
$GLASSFISH_HOME/lib/.

Also, download and copy the commons logging and commons modeller jar files to $GLASSFISH_HOME/lib

Commons logger -> commons-logging-1.1.1.jar from http://commons.apache.org/downloads/download_logging.cgi

Commons modeler -> commons-modeler-2.0.1.jar from http://commons.apache.org/downloads/download_modeler.cgi

Restart Glassfish...


References:

http://weblogs.java.net/blog/jfarcand/archive/2006/03/running_glassfi_1.html

.

Sunday, 9 November 2008

c# code generation added rest describe code gen

Announcement: c# code generation added to google rest describe code gen api:

At last, the google rest describe code gen api now has a c# code generator. Targeting c# .net 3.5 WCF. This gives an easy route from existing services or WADL to c# client code/framework. I hope to be blogging about it soon, with some details of how it works and any limitations you shoud be aware of...


Monday, 3 November 2008

I'm back! Some notes on SELinux and Apache HTTPD

Finally! I took some time out, with a big road trip to America and various other activities going on, I'd not had the time to keep the blog going. Anyway, things are back to normal now and after a recent hard disk failure I unexpectedly found myself setting up a new secure web server using CentOS 5.2 x64 and Apache Httpd 2.2.3 and PHP5. Later I'll add in a Java EE application server for more dynamic/web app stuff.

Thought that I'd type up some small notes on a problem I'd come across before, when trying to setup Mercurial HG-WEB in directories (or sym links) to directories outside of the usual /var/www

One of the problems may come from SELinux. Whilst it's tempting to turn it off, for something facing the public on the web - this would be a real last resort!

Security Contexts: - a quick explanation

Files and directories have security contexts. These can be seen using ls, e.g.

ls -aZ

By default Apache Httpd cannot access all files, it can access those with httpd_sys_content_t context types.

For example user home directories come with the context home_root_t which will give a permission denied type error if httpd tries to serve up files from there (or anywhere below!). Another common security context is default_t which will be assigned as the default for new files and folders.

An important difference between mv and cp

cp creates a new context (inherits), wheras mv actually moves it (unmodified). So a common gotcha is to create files in the user home directory and mv them to /var/www/... but this keeps the home context home_root_t - hence this creates the permission denied error.


Some handy commands:

chcon -R -h -t httpd_sys_content_t /test/

change the directory /test/ to httpd_sys_content security context type, recursively but not following sym-links.

i.e. the above would enable /test/ to be served by a documentroot in Httpd

If SELinux is suspected for the permissions problems (as opposed to httpd configuration), the SELinux restrictions will appear in the message log:

tail -f /var/log/messages


SELinux boolean flags:

can be read with

getsebool httpd_enable_cgi

and set with

setsebool httpd_enable_cgi true


Invoke the simple GUI configurator with: system-config-securitylevel


Restore the file context
(say after an mv command):

restorecon -R -v ./folderwithwrongcontext/


Additional SE Linux parameters:

Enable Samba to access home dirs:

setsebool -P samba_enable_home_dirs=1


Additional Resources:

Good overview in this link: http://docs.fedoraproject.org/selinux-apache-fc3/sn-simple-setup.html



Friday, 18 July 2008

An interesting query for potential optimisation...?

Just wanted to capture a query I was working on yesterday which was slightly 'interesting' in that it consists of a couple of layers of left outer joins and the joining with a derived aggregation table - and time permitting I'd like to revisit it because I'm sure it can be improved / optimised (but it is functionally correct).


select
t1.tid,
t1.alias as alias,
t1.asset_label as asset_label,
t1.terminal_id as terminal_id,
t1.location_address as terminal_address,
t1.last_updated as last_connection,
t1.name as questionnaire_name,
t1.questionnaire_id as questionnaire_id,
t1.state as state,
t1.value as publishing_state,
response_stats.rcount as rcount,
response_stats.last_response as last_response
from
(select
t.id as tid,
t.alias,
t.asset_label,
t.terminal_id,
t.location_address,
t.last_updated,
qnr.name,
qnr.id as questionnaire_id,
qnr.status as state,
at.value
from terminal t
left outer join
(delivery_stats d,
terminal_activity ta,
questionnaire qnr,
activity_type at)
on
d.terminal_id = t.id
and d.terminal_activity_id = ta.id
and ta.questionnaire_id = qnr.id
and ta.activity_type = at.id
and qnr.status = "L"
where
t.id in(1, 20, 21, 22, 23)) as t1
left outer join
(select
tcq.terminal_id tid,
tcq.questionnaire_id qid,
count(*) rcount,
max(uploaded_date) as last_response
from
tcquestionnaire tcq
group by
tcq.terminal_id, tcq.questionnaire_id) as response_stats
on
t1.tid = response_stats.tid
and t1.questionnaire_id = response_stats.qid;


Whilst technically correct - I'm not entirely satisfied of the need for the the top level left outer join which creates a full derived table rather than having a correlated sub-query / nested join that contains only the rows actually relevant to the result set. Something to think about perhaps, on a rainy (very rainy!?!) day :)

.

Wednesday, 16 July 2008

Update vmware server 2.0 from beta 2 to rc1

Just some quick notes on this "upgrade" from beta 2 to rc1 - which is more of a reinstall!

Note: pre-release versions forcefully expire (becomes rather apparent when starting a vmware instance) - but the error message is not that clear - "Failed to start, General error" may appear in the logs as the error but is preceded by a more subtle "version expired, there's a new version out" type message - which is the actual problem.

Basic steps:

Stop/suspend all vm's

Stop services
#service vmware stop

[Recommended - move VMs (for safety/paranoia!), simply mv the whole vmware directory]
[Recommended - good time to check system is up-to-date]

Remove/uninstall existing version (based on 2.0 beta2):
#rpm -e VMware-server-e.x.p-84186.x86_64

install rc1
#rpm -ivh VMware-server-2.0.0-101586.x86_64.rpm
or
#rpm -Uvh VMware-server-2.0.0-101586.x86_64.rpm

configure as per normal
#vmware-config.pl

check running via web management console

service vmware stop

move vmware images back

start services again

Note, VM images have to be reloaded into the VM inventory - apart from that everything is entirely straightforward!

Alternative approach from tarball:

#tar xvfz VMware-server-*.tar.gz

#vmware-server-distrib

#vmware-install.pl


Some relevant links:

http://communities.vmware.com/thread/154503?tstart=0
http://communities.vmware.com/thread/154668?tstart=0
http://communities.vmware.com/message/901195;jsessionid=77A29EE9DF1ADEBF37027EB347D638F3
http://www.cyberciti.biz/tips/vmware-on-centos5-rhel5-64-bit-version.html
http://kirkpbm.wordpress.com/category/vmware-server/
http://communities.vmware.com/docs/DOC-4111
http://communities.vmware.com/thread/143674

.

Saturday, 12 July 2008

OpenSolaris - upgrade to b93

More notes on OpenSolaris image-update, to b93 (in my case from b91)

See this thread http://opensolaris.org/jive/thread.jspa?messageID=258127&#258127 discussing the problem and it's solution.

Performing the standard image-update failed with an error of the form:

> pkg: attempt to mount opensolaris-3 failed.
> pkg: image-update cannot be done on live image

The problem is caused by:

2387 libbe.so:beCopy() frees nvlist variables before using them
http://defect.opensolaris.org/bz/show_bug.cgi?id=2387

So, time to find a work around. This wasn't as seamless as perhaps it should have been, this is how I did it:

#beadm list

> my active BE was opensolaris-3, which I was booted in

#export PKG_CLIENT_TIMEOUT=2000

#pfexec pkg refresh

create a temp BE
#pfexec beadm create opensolaris-4

mount it as /mnt
#pfexec mount -F zfs rpool/ROOT/opensolaris-4 /mnt

update it
#pfexec pkg -R /mnt image-update

#pfexec beadm unmount opensolaris-4

#pfexec beadm activate opensolaris-4

reboot into BE opensolaris-4 build 93

Note: b92 was skipped (not released)!

Also, this failed _every time_ when attempting it from desktop terminal (graphical login) - but worked as soon as I did the same thing from an ssh terminal!

Blog for installing / configuring mysql as service using gui http://weblogs.java.net/blog/bleonard/archive/2008/06/opensolaris_200_3.html


Additional notes:

BE_PRINT_ERR=true can be used to output diagnostic error logs from the be process,

e.g.

BE_PRINT_ERR=true beadm create test


.

Thursday, 10 July 2008

C# delegates

A quick note on c# delegate functions:

I found the standard way to define delegates a little clumsy and verbose in some situations, for example when wanting to pass a function to a .Invoke method of a control to add it to its thread work queue. In this situation the delegate's purpose is really just to pass the method to the invoker, there is no other use of the delegate so declaring it at class level is a much wider scope that I would like. What I wanted is a more terse, compact and locally scoped way to achieve the same thing, here it is:

The simple way:

Declare delegate within class, e.g.

public delegate void updateStockView(Stock[] stocks);

use to create a new delegate instance to pass to invoke on a control, e.g.

instrumentDgv1.Invoke(new updateStockView(this.updateStockView), new object[] {instrumentResponse.Stocks});

This approach, whilst perfectly valid feels a little cumbersome. Firstly the delegate is at an uneccessarily high level of scope, secondly, the statment requires a new instance of the delegate to be created, passing the delegate's parameters down as an object array.

A more compact form:

instrumentDgv1.Invoke((MethodInvoker)delegate { this.updateStockView(instrumentResponse.Stocks); });

Here we see, no unnecessary declaration of the delegate type, no creation of the delegate instance, no passing of parameters as an object array - all round much tighter syntax for this type of use.

The key thing to make this work is the MethodInvoker cast. MethodInvoker is from the System.Windows.Forms namespace and is used to cast the existing method to the delegate type without requiring the declaration/instantiation of a new delegate.

.

Monday, 7 July 2008

Netbeans 6.1 Rest JSR-311 RI library problem

Found a minor problem with Netbeans 6.1 and Rest (Jersey RI) today, thought I'd capture the problem and solution.

Symptom:
Can't launch a Rest application using Jersey (JSR-311 RI) libraries - error given is:

HTTP status 500

exception

javax.servlet.ServletException: java.lang.NoSuchMethodError: javax.servlet.jsp.JspFactory.getJspApplicationContext(Ljavax/servlet/ServletContext;)Ljavax/servlet/jsp/JspApplicationContext;
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:274)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

Because the Jersey (JSR-311 RI) libraries include jsp 2.0 jsp-api-2.0-20040521.jar from Netbeans6.1\enterprise5\modules\ext\rest\ which is an older version of the JSP API.

Fix, copy a newer jsp in or remove the entry from the library definition and add a newer jsp library in.


Example Solution:

Go to tools\libraries
Select the Jersey libary
In the Library classpath, remove the offending jsp-api-2.0-20040521.jar
Now add the newer JSP libary, e.g. Netbeans 6.1 ships with servlet2.5-jsp2.1-api.jar one level up in the Netbeans6.1\enterprise5\modules\ext\ directory.
Remove the Jersey libraries from your project (if already added).
Re-add the Jersey libraries to your project and recompile - problem solved.

Wednesday, 25 June 2008

Stunnel and wcf 3.5 https testing, an easy dev setup

Just some quick notes:

Stunnel can act as an https proxy which is very convenient when you need to test / develop against https but don't want to set up or use a proper environment with real certificates etc in the short term.

I wanted to capture some packet traces of WCF3.5 over an https keep alive channel to a Jboss app server serving normal http on the default 8080 - here's what I did:

Download / install Stunnel. The installation process creates a default .pem self signed certificate (sufficient for dev purposes).

Default Stunnel config is in stunnel.conf (or stunnel.cfg on Linux).

For simple https proxying from the standard port 443 to port 8080, the basic condensed configuration in stunnel.conf looks like:

cert = stunnel.pem
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
debug = 7
output = stunnel.log
[https]
accept = 443
connect = 8080

where we can see the default certificate is being used and I've enabled logging. HTTPS listening on 443 and connecting through to HTTP on 8080 (happened to be Jboss in this instance).

Simple enough, what next. Running the WCF client application - it will barf over the certificate not being trustworthy (an error of the form):

login failed Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost'


Overriding .NET WCF 3.5 default certificate policy to allow all certs for testing/dev purposes


For test/dev purposes it's often handy to allow all certificates.

What you can do is override the certificate checking policy to "say yes to everything" (Remember to take this out for product release!)

The code looks something like this:

using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

...

// ***** WARNING - to be removed for release! *****
ServicePointManager.ServerCertificateValidationCallback +=
delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{ return true; };


Which is using an anonymous delegate callback to return true in all cases (true = accept) - which keeps the code nice and compact.

If you're specifically testing keep alive then these additional parameters for stunnel.conf control how the proxy behaves in terms of connection persistence:

session = 300
TIMEOUTclose = 0
TIMEOUTidle = 180


Friday, 20 June 2008

OpenSolaris 2008.05 & update to >= b90

With the demise of SXDE I thought I'd prepare for life with OpenSolaris...

Currently on build 90, 2008.05 represents build 86.

Installation of OpenSolaris 2008.05 from the Live CD (1 CD) is a breeze, simply boot from the CD (this took some time under VMWare!), have a play then click the install link on the desktop - great!

OS2008.05 uses ZFS and IPS - so this is a good starting point and upgradable using a package management system rather like we've all come to expect from the Linux world :)

Once installed, you can use pkg image-update to udate to the latest build of OpenSolaris, here are some quick notes:

set a timeout to avoid disapointment during the udate process!

#export PKG_CLIENT_TIMEOUT=2000


#pkg refresh


#pfexec pkg image-update



# important - do this before reboot! (or your reboot won't [boot])

http://mail.opensolaris.org/pipermail/indiana-discuss/attachments/20080606/94969481/attachment-0003.txt

Which boils down to:

#beadm list
Check the active on reboot name, e.g. opensolaris-1

#pfexec mount -F zfs rpool/ROOT/opensolaris-1 /mnt

#pfexec /mnt/boot/solaris/bin/update_grub -R /mnt


A guide for OpenSolaris installation under vmware:

http://blogs.sun.com/souvik/entry/getting_started_with_opensolaris_2008

Another good thread: http://opensolaris.org/jive/thread.jspa?threadID=62982&tstart=0

--

Install Java JDK and Netbeans:

http://blogs.sun.com/souvik/entry/getting_started_with_opensolaris_2008



#zcat jdk-6u6-solaris-i586.tar.Z | tar -xf -

#pfexec pkgadd -d . SUNWj6dev SUNWj6cfg SUNWj6man SUNWj6dmo


NB: after installing the 32bit version the 64bit extensions can be installed but don't do this if you want to use applets or web start.

Install FireFox 3:

http://opensolaris.org/jive/thread.jspa?messageID=250311&tstart=0


Installing mysql etc:

#pfexec pkg install SUNWapch22 SUNWmysql5 SUNWapch22m-php5 SUNWphp524-mysql

http://blogs.sun.com/natarajan/entry/how_to_install_apache_php

--

Check platform 32/64 bit:

#isainfo -b

Monday, 2 June 2008

Integrating REST POX web services and .NET WCF

Notes:

WCF 3.5 supports REST POX services using the web service model.

WebHttpBinding supports cookies for session support etc, e.g:

WebHttpBinding webHttpBinding = new WebHttpBinding();
webHttpBinding.AllowCookies = true;

using (ChannelFactory cf = new ChannelFactory(webHttpBinding, hostPath))
{ ...

Issues:

  • WebInvoke method POST: post data sent only as JSON or XML - no support for simple form encoded parameters.
  • General inflexibility when mixing types of data or overloading services make it harder to leverage existing services that support existing AJAX/rich Internet systems.


Blogs, articles and useful resources:

http://bitworking.org/news/125/REST-and-WS

HTTP Programming with WCF and the .NET Framework 3.5 - http://msdn.microsoft.com/en-us/magazine/cc135976.aspx

http://msdn.microsoft.com/en-us/library/system.servicemodel.aspx

http://hyperthink.net/blog/2008/01/18/WCF+Web+Programming+Model+Documentation.aspx

http://msdn.microsoft.com/en-us/library/bb412176.aspx

Rick Strahl's excellent articles:

How to consume REST services with WCF - http://blogs.msdn.com/pedram/archive/2008/04/21/how-to-consume-rest-services-with-wcf.aspx

Simple example with DataContract: http://dev.aol.com/node/595

A set of WCF tutorials:

http://dotnet.org.za/hiltong/pages/Windows-Communication-Foundation-_2800_Indigo_2900_-Hello-World-Tutorial.aspx



Interesting problem with XML serialiser quota that you could run into at some point:

http://www.timrayburn.net/2007/10/02/XmlSerializerFormat+Plus+Huge+Schema+Equals+Trouble.aspx

Wednesday, 21 May 2008

REST WADL - tools and information

I'm interested to use REST or REST-like web services within a traditional thick client (as well as AJAX web apps) - using WADL to describe them (from existing services) and tools to automatically generate client API code (in a variety of languages).

Standards:
  • JAX-RS (JSR 311)

Digging around, I come across some interesting articles and blogs, including:

REST Describe and REST Compile:

Thomas Steiner's blog http://blog.tomayac.de/index.php?date=2007-03-12&time=17:11:27&perma=Automatic+Multi+Lang.html describing two tools to be developed.


Java.Net resources:

Other resources and blogs:

http://blogs.msdn.com/dotnetinterop/archive/2008/02/06/wadl-and-wsdl-and-rest-oh-my.aspx

An article on REST WADL http://searchsoa.techtarget.com/tip/0,289483,sid26_gci1265367,00.html

Blog by William Martinez Pomares with interesting follow up discussion http://acoscomp.com/wblog//index.php/a/2007/06/10/wadl_rest_and_wsdl


REST Describe and REST Compile tools:

Trying the on-line REST Describe on an existing web service I'd published previously showed promising results.

The current status of REST Compile is that is supports:
  • Java
  • PHP5
  • Ruby
  • Python

but .Net is not provided as yet.

Friday, 2 May 2008

Solaris 10, X fails to start after installing VMWare tools

Note to self - if this happens restore the pre-installation vmware_drv.so as per this link:

http://communities.vmware.com/thread/93366

and this one too http://knowledgefrontier.blogspot.com/2008/04/opensolaris-snv86-on-vmware-with.html

which is essentially to do this:

mv /usr/X11/lib/modules/drivers/vmware_drv.so.BeforeVMwareToolsInstall /usr/X11/lib/modules/drivers/vmware_drv.so

luckily vmware keeps the old copy, which is handy....

this is dead easy when you know it. When it only shows up as a problem after a reboot, and the time between installing the tools and rebooting is days or weeks with many other changes in-between - working out the cause and effect relationship is not always so obvious :)

Thursday, 1 May 2008

Blastwave for easy Apache http 2.2 and mod_jk, on Solaris SXDE 10

Goal: Install mod_jk for Apache http 2.2.x with minimal effort!

Such that Apache http can be tested as a front for Glassfish 2ur2 (rather than the usual Tomcat) using the same mod_jk connector...

A handy binary of mod_jk for Solaris and the right version of Apache http didn't seem readily available.

Here are some quick notes on Solaris, Blastwave, Apache httpd and mod_jk

Decided to try out the Blastwave software repository for CSW, site is here http://www.blastwave.org/

Rough steps as follows:

Follow http://www.blastwave.org/howto.html

which is essentially:

pkgadd -d http://www.blastwave.org/pkg_get.pkg
/opt/csw/bin/pkg-get -i wget

/opt/csw/bin/pkg-get -i apache2
/opt/csw/bin/pkg-get -i ap2_mod_jk

and optionally:

cp -p /var/pkg-get/admin-fullauto /var/pkg-get/admin

check the exact version installed:

/opt/csw/apache2/sbin/httpd -v

stop existing service installed as part of SXDE:

svcadm disable apache22
svcs apache22

check lib dsos:

/opt/csw/apache2/libexec

start the server manually:

/opt/csw/apache2/sbin/apachectl start
/opt/csw/apache2/sbin/apachectl stop


Todo:

Configure Apache http and mod_jk
Configure Glassfish with libs etc
Test web applications including failure conditions
Set Blastwave installed version as a service

Wednesday, 23 April 2008

Some quick notes on Db Connection pooling in Glassfish

To set up a Glassfish connection pooling and JNDI datasource, accessible in your web app, the following things need to be done (tried with Glassfish v2):

Db drivers:

Ensure the relevant JDBC driver is in the Glassfish classpath. I ensured the <glassfish_home>/lib directory contained the latest MySQL J connector. You may need to restart Glassfish (you probably will if you change the classpath).

Configuration:

Connection Pool:

Set up a connection pool in the Glassfish admin interface (under Resources\JDBC\Connection Pools). In my case for MySQL I was happy to use the defaults initially, which includes:

  • Datasource classname: com.mysql.jdbc.jdbc2.optional.MysqlDataSource
  • Resource Type: javax.sql.Datasource

Give the pool a sensible name.

Once you have set this and the connection details (host, username, password etc) you can use the Ping feature to check the connectivity. If you get errors regarding classes not found, check your classpath / location of the JDBC library jars - possibly restart Glassfish if you have not already.

Once you have a successful ping, you can move on to configuring the JNDI resource:

JNDI resource:

Under the Resources\JDBC\JDBC Resources set up a JNDI resource to the pool you just configured (by name), give the JNDI resource a name of the form:

jdbc/myLovelyDbJNDIResourceName

ensure the resource is enabled!

Deployment descriptors, configuration:

sun-web.xml - Map the container JNDI to a resource reference in sun-web.xml, e.g. something like:

<!-- Map container JNDI to resource reference -->
<resource-ref>
<res-ref-name>myDbResourceName</res-ref-name>
<jndi-name>jdbc/myLovelyDbJNDIResourceName</jndi-name>
</resource-ref>

web.xml - Map the resource as a datasource reference in web.xml

<!-- set up resource reference for the web app -->
<resource-ref>
<res-ref-name>myDbResourceName</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

Application Code:

In you application code, where you get a connection, you can then use something along the lines of:


Connection connection = null;

try
{
Context env = (Context)new InitialContext().lookup("java:comp/env");

DataSource pool = (DataSource)env.lookup("myDbResourceName");

if (pool == null)
{
throw new RuntimeException("Unknown DataSource");
}

connection = pool.getConnection();
}
catch(NamingException ne)
{
throw new RuntimeException(ne.getMessage());
}

return connection;

Of course, modify the caught, declared to throw exceptions to suit the application design...

References:

This article is a useful reference point, covering similar information in a slightly more verbose form:

http://thestewscope.wordpress.com/2008/01/08/glassfish-v2-ur1-and-mysql-connection-pool/

This forum post also details the deployment descriptor configuration well:
http://forums.java.net/jive/message.jspa?messageID=264629

Tuesday, 22 April 2008

Mobile development with .NET CF

It's been a few days since the last posting, I've been meaning to jot down some notes from the workshop at Microsoft (Reading Uk, 16-April-2008) before anything gets forgotten:

The aim of the workshop was to discuss the use of the Microsoft .Net Compact framework for mobile application development - including performance issues and technology features. This was in the context of both our existing Java mobile applications and choosing suitable technologies for new projects.

Java ME J9 6.1.1 performance evaluation:

To illustrate the performance we'd experienced with out Java ME applications, we demoed our existing Java ME application running on IBM J9 CDC ppro1.1 on an IPAQ. The response was actually very positive. It was suggested that re-implementing it in .Net would not yield any worth while performance gains but it would most likely create a different set of problems to solve.

We ran our app with JIT enabled, noverify and nolinenumbers but it was not compiled as a JXE on this occasion. Focus was on running application performance as perceived through the GUI (user perceptions), we did not delve into profiling information. We did not look into start up times, which are roughly similar for both Java and .Net VM based technologies.

.Net CF:

.Net CF does provide some benefits, in terms of integration with the Windows operating system (integration with the Windows menu bars etc) that would be worth bearing in mind for future projects. Specifically, notification of docking events could prove very useful in some situations. Native code is supported, as external libraries (not within the assembly) but hooks into the OS API are possible by declaring them within the .Net assembly.

Versions / dependencies:

For .Net development some care regarding versions and dependencies should be considered, for example whilst versions of Windows Mobile from 5.0 onwards _should_ support any version of .Net CF, the same can not be guaranteed for the more variable CE, where platform vendors could load a CE image missing key components required for installing .Net CF. In this scenario it would be important to discover this and engage with the customer and platform vendor to negotiate shipment of hardware with the right image components installed.

.Net CF versions:

  • 1.0 -> Old original version, no longer targeted by most development
  • 2.0 -> Good baseline with significant improvements (including performance) over 1.0 (required MS VS 2005 IDE to develop).
  • 3.5 -> Current latest version (required MS VS 2008 Pro IDE to develop).

Windows Mobile versions against their CE base:

  • WM 2003 'Ozone' -> CE 4.20
  • WM 5.0 'Magneto' -> based on CE 5 (shipped with .NET v1.0 SP2)
  • WM 6 .0 'Crossbow' -> based on CE 5.2 (shipped with .NET CF v2.0 SP2 )
  • WM 6.1 -> CE 5.x ? TBA
  • WM 7.0 'Photon' -> CE 6.0? TBD

The next major version of Windows Mobile is anticipated in 2009, but no official details were given. General information suggests a planned release of Windows Mobile 7 in the 2nd half of 2009.

CE 6.0 removes the 32 process and 32Mb restrictions:
  • The 32 process limit raised to 32,768 processes.
  • The 32 megabyte VM limit raised up to 2GB of private VM is available per process.

Technologies:


Microsoft SQL Server 2005 Compact Edition is available (shipped with WM 6.0). This can be used stand alone, or connected to a server side SQL server. Can be synchronised with server DB over network. Async and synch operation is possible. Loads in process as a dll (therefore doesn't use any precious process slots, but of course it will consume RAM/processor). This is a very cut down DB, things such as triggers and stored procedures are not supported.

Ajax, DOM, Javascript is possible in the browser technology (from WM 6.0 onwards).

XML is supported - recommended to use XML readers not full blown XML DOM for efficiency reasons.

XSLT - it was not clear weather XSLT was supported on the platform, either in the browser or as .Net libraries.

Windows Mobile limitations (until WM 7.0):
  • 32 process limit
  • 32Mb memory limit

Windows Mobile can close applications when it starts to run low on resources - so applications should be developed with this in mind. The OS will pick the lowest application in the Z-order that is inactive. Notification events are sent but if the application doesn't respond gracefully it could receive hard termination!

.Net development tools:

Visual studio is the only supported option (no free express version for CF 3.5 available at this time).

Optimisation tools were not generally recommended - they advocate letting it run 'as-is' but rather to concentrate efforts on getting the design right.

It was admitted that profiling tools were somewhat weak at the moment - but this is an area they are actively addressing.

Code signing:

We were warned that some platform vendors have removed the root CA from the device, which means that the only option for getting the application code signed would be to go through the device vendor (this is something that would need to be highlighted and planed in early in the project).

Testing:

The need for thorough and extended testing was highlighted. Mainly due to the additional use cases that can occur on a mobile platform that are less likely or non-existent on a traditional desktop pc system, for example:

  • Memory cards being removed
  • Wireless signal poor / dropped
  • Flat battery, battery removal
  • Unexpected key presses from special function keys on the device

.Net configuration:

It's possible to configure the platform .Net CF using a configuration file:

http://msdn2.microsoft.com/en-us/library/bb629366.aspx

Software updates:

Whilst there is no application support for software updates (apart from the M ) there are some software components that can be used as a basis for providing this, the Mobile Client Software Factory and the Mobile Updater.

http://www.microsoft.com/downloads/details.aspx?FamilyID=F9176708-9F57-4C0F-97FB-F9C65A9BBF22&displaylang=en

http://msdn2.microsoft.com/en-us/library/bb629366.aspx

Additional links and info:

Mobile Dev centre http://msdn2.microsoft.com/en-gb/windowsmobile/default.aspx

Application developer consulting service http://www.microsoft.com/uk/adc

Libraries and widgets:

Mobility Marvels: http://msdn2.microsoft.com/en-us/windowsmobile/bb250537.aspx

Mobile Controls: http://www.asp.net/mobile/

Tuesday, 15 April 2008

Xephyr on Solaris

Searching for a better Xnest on Solaris, looking for Xephyr as a package or source to build, it turns out Xephyr is already included in SXDE.

location: /usr/X11/bin

simple usage example:

Xephyr :1 -screen 1200x800 -query localhost

This what's new in SXDE 10 guide is quite handy http://dlc.sun.com/pdf/817-0547/817-0547.pdf

Early signs of Xephyr -> ssh -> Xming on Windows seem reasonable.


ProGuard - new 4.2 version:

Evaluated the latest ProGuard 4.2 for our Java ME mobile client and it failed reporting a stack length had gone negative! Have reverted back to 4.1 for now, which seems to be working well. Will report the bug to the team.

Java ME, some J9 options worth remembering:

-Xint -> disable AOT and JIT, interpreted mode only
-noverify -> disable class verification checks (faster loaded on pre-verified code)
-Xnolinenumbers -> turn off line number debug info