Sunday, March 28, 2010

Killing an annoying warning

The most annoying warning ever has been haunting me for a while.

[javac] /home/razvanc/workspace7u6/razxml/src/razie/base/data/RiXmlUtils.java:160: warning: com.sun.org.apache.xpath.internal.objects.XObject is Sun proprietary API and may be removed in a future release


I refuse to include and move around large unnecessary libraries to deal with XML and XPATH just because Sun considers themselves the center of the universe and their internal libraries somehow more important then mine. In short, they figured there should be no way to remove this warning, although, in this case, they copied code from apache into their own libraries.

Well, the solution is rather simple. Most likely everyone has specific XML wrappers. Just put them in their own project, disable the java/scala builders. Then, build it manually, create a jar file and check it in.

Then, in all the other projects, use this jar directly. Since the jar is already compiled, the annoying warning is no more.

See for instance my xml utilities, at http://github.com/razie/razxml

What's more, I don't actually use the XML stuff directly. I wrapped it all in pretty much one single class, using XPATH for access. It's simple, fast enough and makes for very simple code:


Reg.doc(MediaConfig.MEDIA_CONFIG).xpa(
"/config/storage/host[@name='" + Agents.me().name + "']/media/@localdir"
)


For all xml data access, you should limit yourself to the xpe/xpl/xpa methods described in an earlier post (http://blog.homecloud.ca/2010/02/one-xpath-to-rule-them-all.html). So, use something like this instead: http://github.com/razie/razxml/blob/master/src/razie/base/data/XmlDoc.java

Cheers.

Saturday, March 13, 2010

The Option monad pattern thing

Having options is cool...even scala's Option[A]... :)

One way to use Option is plain:


addressMap.get("John") match {
case Some(addr) => popupMap (addr)
case None => logError(...)
}


or "java style" (synonym with "plain ugly"):


x = addressMap.get("John").getOrElse (null)
if (x != null) {
popupMap (x)
} else {
logError(...)
}



As you use scala more, you understand why monads are elephants and start doing it nice:


addressMap.foreach (popupMap(_))


addressMap.map (_.city)



And then you start to understand it as a pattern, basically you understand there's a range of problems were options apply. Say you create a small scripting framework (the same applies to say a command pattern framework). A script's execution may return successfully and with a value, or give a syntax error or a bunch of other options.


// the result of running a smart script



class RSResult {
def foreach (f:Any=>Unit) {}
def map (f:Any=>RSResult) : RSResult = RSUnsupported
def getOrElse (f: => Any) :Any = f
def jgetOrElse (f:Any) :Any = getOrElse(f)
}

case class RSSucc (res:Any) extends RSResult {
override def foreach (f:Any=>Unit) { f(res) }
override def map (f:Any=>RSResult): RSResult = f(res)
override def getOrElse (f: => Any) : Any = res
}

case class RSError (err:String) extends RSResult
object RSIncomplete extends RSResult // expression is incomplete...
object RSUnsupported extends RSResult // interactive mode unsupported
object RSSuccNoValue extends RSResult // successful, but no value returned



And then, of course, the methods returning these:






I used Any instead of [A] for simplicity, but there you have it. The Option monad pattern thing. Pretty cool!





Monday, March 1, 2010

Scripster - interactive scala REPL using telnet, http etc

As mentioned before, I think that all apps must alllow scripted/programatic access to their objects.

I created a simple interactive gate to acces the scala REPL in any scala process. It only uses one port and supports telnet, http and swing:



The graphics are based on my 20widgets project, with the addition of a ScriptPad widget.

Content assist is only available in the telnet version (sic!). I will work to find some nice syntax-colored controls for the web version. Switch to character mode ("mode character" on ubuntu or default on windows) and use TAB to see a list of options. Right now it's a demo only, I need to find the parser's APIs to get the real content assist options ;)

You can download the single scripster-dist.jar file from my razpub project download, at http://code.google.com/p/razpub/ and run the example with this command line (replace /host/bin/scala with your $SCALA_HOME) :

java -classpath ./scripster-dist.jar:/host/bin/scala/lib/scala-library.jar:/host/bin/scala/lib/scala-compiler.jar:/host/bin/scala/lib/scala-swing.jar razie.scripster.JScalapSwing


To use it in your process, put these jars in your classpath and use this:
razie.scripster.Scripster.create(4445)
where 4445 is the port you want to use, see the razie.scripster.MainScripster for an example. To enable the swing version, use the swing jars as well and see the razie.scripster.MainSwingScripster class for an example.

For further tweaking, look at the code yourself, at http://github.com/razie/scripster/tree/master/src/razie/scripster/

If you want to keep in touch with the evolution of scripster or my other related endeavours, subscribe to the RSS feed or twitter/razie.

Scripster's main page, kept up-to-date, is at http://wiki.homecloud.ca/scripster. There's also an online live demo at http://scripster.codewitter.com.

Enjoy!