Navigation

RSS 2.0 New Entries Syndication Feed Atom 0.3 New Entries Syndication Feed

Show blog menu v

 

General

Use it

Documentation

Support

Sibling projects

RIFE powered

Valid XHTML 1.0 Transitional

Valid CSS!

Blogs : Archives

avatar
< Native Java Continuations   Anonymous disrespect >
Getting rid of XML with Groovy and Janino

Update: it seems that I failed to have brought accross that the visual look is not very important to me. However, you get actual functionality in your configuration files without necessarely having to give up a structured configuration format. Both the Groovy as the Janino examples are full languages and all the power of them is available right in the configuration files *and* processed dynamically and reloaded.

For a while I've been getting more and more irritated by XML. I don't like how I have to type in tags, how I have to escape text, how everything is passed in as regular text without any typing ... how unlike a regular programming language it is. XML might be great for portable document formats, but for configuration it now feels totally inappropriate.

So today I implemented a few alternative RIFE site structure configuration methods thanks to Groovy and Janino.

I'm very pleased with the results and the Janino version really feels nice. The fact that it's standard Java makes it possible to use all the features of my IDE (code completion, on-the-fly error checking, ...) and still have the benefit of a concise syntax and automatic reloading.

I have done the Groovy version in a similar way, but I only showed what the BuilderSupport class offers more. So the Groovy version is actually able of taking both approaches.

Take a look at the results:

Regular XML

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE site SYSTEM "/dtd/site.dtd">

<site fallbackid="ELEMENT4">
    <globalexit name="globalexit1" destid="ELEMENT6"/>
    <globalexit name="globalexit2" destid="SUBSITE.ELEMENT2"/>

    <globalvar name="globalvar1"/>
    <globalvar name="globalvar2"/>
    
    <subsite id="SUBSITE" file="xml/test_xml2sitesubsite.xml" urlprefix="/subsite" inherits="ELEMENT4"/>
    
    <group inherits="ELEMENT5">
        <globalvar name="globalvar4"/>
     
        <element id="ELEMENT6" file="xml/test_xml2elementinfo2.xml" url="/test/element6" inherits="ELEMENT3"/>
        <element file="xml/test_xml2elementinfo3.xml" url="/test/element7"/>
    </group>
    
    <element id="ELEMENT1" file="xml/test_xml2elementinfo1.xml" url="/test/element1">
        <datalink srcoutput="output1" destid="ELEMENT2" destinput="input1"/>
        <datalink srcoutput="output1" destid="ELEMENT2" destinput="input2"/>
        <flowlink srcexit="exit1" destid="ELEMENT2"/>
        <flowlink srcexit="exit2" snapback="true"/>
        <datalink srcoutput="output2" snapback="t" destinput="input2"/>
    </element>
    
    <element id="ELEMENT2" file="xml/test_xml2elementinfo2.xml" inherits="ELEMENT3" url="/test/element2"/>
             
    <element id="ELEMENT3" file="xml/test_xml2elementinfo3.xml"/>

    <element id="ELEMENT4" file="xml/test_xml2elementinfo4.xml"/>

    <element id="ELEMENT5" file="xml/test_xml2elementinfo5.xml"/>
</site>

Groovy

processor.site(fallbackid:"ELEMENT4") {
    globalexit(name:"globalexit1", destid:"ELEMENT6")
    globalexit(name:"globalexit2", destid:"SUBSITE.ELEMENT2")

    globalvar(name:"globalvar1") {
            defaultvalue("default1")
        }
    globalvar(name:"globalvar2")
    
    subsite(id:"SUBSITE", file:"groovy/test_groovy2sitesubsite.groovy", urlprefix:"/subsite", inherits:"ELEMENT4")
    
    group(inherits:"ELEMENT5") {
        globalvar(name:"globalvar4")
     
        element(id:"ELEMENT6", file:"groovy/test_groovy2elementinfo2.groovy", url:"/test/element6", inherits:"ELEMENT3")
        element(file:"groovy/test_groovy2elementinfo3.groovy", url:"/test/element7")
    }
    
    element(id:"ELEMENT1", file:"groovy/test_groovy2elementinfo1.groovy", url:"/test/element1") {
        datalink(srcoutput:"output1", destid:"ELEMENT2", destinput:"input1")
        datalink(srcoutput:"output1", destid:"ELEMENT2", destinput:"input2")
        flowlink(srcexit:"exit1", destid:"ELEMENT2")
        flowlink(srcexit:"exit2", snapback:true)
        datalink(srcoutput:"output2", snapback:true, destinput:"input2")
    }
    
    element(id:"ELEMENT2", file:"groovy/test_groovy2elementinfo2.groovy", inherits:"ELEMENT3", url:"/test/element2")
             
    element(id:"ELEMENT3", file:"groovy/test_groovy2elementinfo3.groovy")

    element(id:"ELEMENT4", file:"groovy/test_groovy2elementinfo4.groovy")

    element(id:"ELEMENT5", file:"groovy/test_groovy2elementinfo5.groovy")
}

Janino

builder
    .setFallback("ELEMENT4")
    
    .addGlobalExit("globalexit1","ELEMENT6")
    .addGlobalExit("globalexit2", "SUBSITE.ELEMENT2")

    .addGlobalVar("globalvar1", new String[] {"default1"})
    .addGlobalVar("globalvar2")

    .enterSubsite("janino/test_janino2sitesubsite.janino")
        .setId("SUBSITE")
        .setUrlPrefix("/subsite")
        .setInherits("ELEMENT4")
    .leaveSubsite()

    .enterGroup()
        .setInherits("ELEMENT5")
    
        .addGlobalVar("globalvar4")
    
        .enterElement("janino/test_janino2elementinfo2.janino")
            .setId("ELEMENT6")
            .setUrl("/test/element6")
            .setInherits("ELEMENT3")
        .leaveElement()
    
        .enterElement("janino/test_janino2elementinfo3.janino")
            .setUrl("/test/element7")
        .leaveElement()
    .leaveGroup()
    
    .enterElement("janino/test_janino2elementinfo1.janino")
        .setId("ELEMENT1")
        .setUrl("/test/element1")
    
        .addDataLink("output1", "ELEMENT2", "input1")
        .addDataLink("output1", "ELEMENT2", "input2")
        .addFlowLink("exit1", "ELEMENT2")
        .addSnapbackFlowLink("exit2", false)
        .addSnapbackDataLink("output2", "input2")
    .leaveElement()
        
    .enterElement("janino/test_janino2elementinfo2.janino")
        .setId("ELEMENT2")
        .setInherits("ELEMENT3")
        .setUrl("/test/element2")
    .leaveElement()
        
    .enterElement("janino/test_janino2elementinfo3.janino")
        .setId("ELEMENT3")
    .leaveElement()
        
    .enterElement("janino/test_janino2elementinfo4.janino")
        .setId("ELEMENT4")
    .leaveElement()
        
    .enterElement("janino/test_janino2elementinfo5.janino")
        .setId("ELEMENT5")
    .leaveElement();
posted by Geert Bevin in RIFE on Jul 22, 2004 3:21 PM : 9 comments [permalink]
 

Comments

Re: Getting rid of XML with Groovy and Janino

From my perspective, none of the above look particularly neat. But, not having to write all the plumbing code to read the XML documents is usually worth the price of admission. I've spent four years now working with XML almost exclusively... and it's not getting any easier. You just don't need it most of the time.

Re: Getting rid of XML with Groovy and Janino

So, you didn't agree with my comment so you deleted it? I just asked a simple question. I won't ask it again because instead of giving an answer, I'm sure you'll delete this post.

Re: Getting rid of XML with Groovy and Janino

Couldn't agree more.

I have seen configuration files for Python programs (Moin Moin for example) that use Python code for config files, the flexibility is just great. You can use the whole power of Python right there, do calculations, reuse common code, conditionals, etc.

It looks like through Janino you can actually write config files directly in Java, which is great.

Your examples should highlight the fact that you can actually have code in your config files.

Re: Getting rid of XML with Groovy and Janino

No, I delete posts from "No one" <noone@email.com>. If you can't be troubled to at least make yourself look human, I can't be troubled to give you an answer.

Re: Getting rid of XML with Groovy and Janino

Is this better? Even if I used my real name, you still wouldn't have a clue who I am.

Re: Getting rid of XML with Groovy and Janino

My question remains. Configuration files are configuration files for a reason, they are static runtime information. If you need a programming language, why not do the whole thing in Java?

Re: Getting rid of XML with Groovy and Janino

If you would have read instead of being an asshole, you'd know that Janino is pure Java that's compiled by an embedded compiler and reloaded automatically. Groovy is a wonderful scripting language that offers everything Java has and much more. Just go to the sites.

Re: Getting rid of XML with Groovy and Janino

Are you related to Russell Beattie?

Re: Getting rid of XML with Groovy and Janino

Obviously 'asshole' doesn't get the point... xml is not the only way to do configuration. Script can *often* be just as good, if not better, in terms of readability and clarity.

However, I don't think that's the case here... the XML seems clearer by a small margin than the Groovy version.

Where Groovy et al really shine is when you need to do some programming-ish things in the configuration. That's where XML gets wildly inappropriate (see XSLT when it comes to doing procedural stuff).

I think maybe what would work better here is something even terser (more terse) than the XML markup.

What I think might be best of all is having some way to easily create custom config editors that can present your configuration in a clear way, while using a more machine-friendly backend to persist the data. That way you could actually use more than ascii text/spacing/punctuation to express the Stuff You're Actually Working On.

Does any of that make sense?

Add a new comment

:) ;)
=) :-)
:'( :(
:/ :D
:| :p
:o 8)
Your email address will not be displayed at anytime on any page.
Only provide your email address if you'd like updates on this entry
and it's comments by email.
Please answer this simple math question:
18 - 4 = 
 
 
  

Manage subscription

Remove email:
 

< Native Java Continuations   Anonymous disrespect >
 
 
 
Google
rifers.org web