Thursday, 18 April 2013

JavaFX JUnit Testing

Unit testing in JavaFX is important but normal JUnit tests will fail because they are not run on the JavaFX thread.  Below is an example of how to solve this. The two classes below take care of loading JavaFX and a JUnit test runner which guarantees that JavaFX is running and makes sure that all tests are run in the JavaFX thread.

This solution is based on a JUnit4 Runner.  The new runner class extends the BlockJUnit4ClassRunner which is the default runner for JUnit tests.  If you also need the spring support then just extend the SpringJUnit4ClassRunner instead. Both runners can co-exist if necessary because they both use the JavaFxJUnit4Application class to guarantee a single JavaFx instance.

JavaFxJUnit4ClassRunner

Runs all the unit tests in the JavaFX Thread.

import java.util.concurrent.CountDownLatch;

import javafx.application.Platform;

import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;

/**
 * This basic class runner ensures that JavaFx is running and then wraps all the runChild() calls 
 * in a Platform.runLater().  runChild() is called for each test that is run.  By wrapping each call
 *  in the Platform.runLater() this ensures that the request is executed on the JavaFx thread.
 */
public class JavaFxJUnit4ClassRunner extends BlockJUnit4ClassRunner
{
    /**
     * Constructs a new JavaFxJUnit4ClassRunner with the given parameters.
     * 
     * @param clazz The class that is to be run with this Runner
     * @throws InitializationError Thrown by the BlockJUnit4ClassRunner in the super()
     */
    public JavaFxJUnit4ClassRunner(final Class<?> clazz) throws InitializationError
    {
        super(clazz);
        
        JavaFxJUnit4Application.startJavaFx();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void runChild(final FrameworkMethod method, final RunNotifier notifier)
    {
        // Create a latch which is only removed after the super runChild() method
        // has been implemented.
        final CountDownLatch latch = new CountDownLatch(1);
        Platform.runLater(new Runnable()
        {
            @Override
            public void run()
            {
                // Call super to actually do the work
                JavaFxJUnit4ClassRunner.super.runChild(method, notifier);
                
                // Decrement the latch which will now proceed.
                latch.countDown();
            }
        });
        try
        {
            latch.await();
        }
        catch (InterruptedException e)
        {
            // Waiting for the latch was interruped
            e.printStackTrace();
        }
    }
}


JavaFxJUnit4Application

Manages starting JavaFX.  Uses a static flag to make sure that FX is only started once.

Manages starting JavaFX.  Uses a static flag to make sure that FX is only started once and a LOCK to make sure that multiple calls will pause if the JavaFX thread is in the process of being started.  This improves on the previous version because it doesn't involve a sleep.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javafx.application.Application;
import javafx.stage.Stage;

/**
 * This is the application which starts JavaFx.  It is controlled through the startJavaFx() method.
 */
public class JavaFxJUnit4Application extends Application
{

    /** The lock that guarantees that only one JavaFX thread will be started. */
    private static final ReentrantLock LOCK = new ReentrantLock();

    /** Started flag. */
    private static AtomicBoolean started = new AtomicBoolean();

    /**
     * Start JavaFx.
     */
    public static void startJavaFx()
    {
        try
        {
            // Lock or wait.  This gives another call to this method time to finish
            // and release the lock before another one has a go
            LOCK.lock();

            if (!started.get())
            {
                // start the JavaFX application
                final ExecutorService executor = Executors.newSingleThreadExecutor();
                executor.execute(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        JavaFxJUnit4Application.launch();
                    }
                });

                while (!started.get())
                {
                    Thread.yield();
                }
            }
        }
        finally
        {
            LOCK.unlock();
        }
    }

    /**
     * Launch.
     */
    protected static void launch()
    {
        Application.launch();
    }

    /**
     * An empty start method.
     *
     * @param stage The stage
     */
    @Override
    public void start(final Stage stage)
    {
        started.set(Boolean.TRUE);
    }
}

Sample Test

A sample test class which instantiates a Scene object.  This will fail if it isn't on the JavaFX thread.  It can be shown to fail if the @RunWith annotation is removed.


/**
 * This is a sample test class for java fx tests.
 */
@RunWith(JavaFxJUnit4ClassRunner.class)
public class ApplicationTestBase
{
    /**
     * Daft normal test.
     */
    @Test
    public void testNormal()
    {
        assertTrue(true);
    }

    /**
     * Test which would normally fail without running on the JavaFX thread.
     */
    @Test
    public void testNeedsJavaFX()
    {
        Scene scene = new Scene(new Group());
        assertTrue(true);
    }
}


JavaFxJUnit4Application - Previous version

Manages starting JavaFX.  Uses a static flag to make sure that FX is only started once.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javafx.application.Application;
import javafx.stage.Stage;

/**
 * This is the application which starts JavaFx.  It is controlled through the startJavaFx() method.
 */
public class JavaFxJUnit4Application extends Application
{
    /**
     * Flag stating if javafx has started. Static so that it
     * is shared across all instances.
     */
    private static boolean started;
    
    /**
     * Start JavaFx.
     */
    static void startJavaFx()
    {
        if (started)
        {
            return;
        }
        
        started = true;
        
        /**
         * The executor which starts JavaFx.
         */
        final ExecutorService executor = Executors.newSingleThreadExecutor();

        // Start the java fx application
        executor.execute(new Runnable()
        {
            @Override
            public void run()
            {
                JavaFxJUnit4Application.launch();
            }
        });

        // Pause briefly to give FX a chance to start
        try
        {
            Thread.sleep(1000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
    
    /**
     * Launch.
     */
    static void launch()
    {
        Application.launch();
    }

    /**
     * An empty start method.
     * 
     * @param stage The stage
     */
    @Override
    public final void start(final Stage stage)
    {
        // Empty
    }
}

Friday, 15 February 2013

JavaFX Pan & Zoom

These notes are based around putting objects into a normal Pane object and not, for example, a ScrollPane where the rules for finding the centre point to pivot a scale around are a bit odd!

JavaFX gives amazing controls over panning and zooming.  For example to pan a pane you can simply use

    pane.setTranslateX(10);
    pane.setTranslateY(10);

This will set the translate.  If you want to move an object more from its currently panned position use

    pane.setTranslateX(pane.getTranslateX() + ...);
    pane.setTranslateY(pane.getTranslateY() + ...);

Zooming is very similar, to double the size around the centre point of the pane,

    pane.setScaleX(2);
    pane.setScaleY(2);

Putting these together is fine and works well.  However, you would normally want to zoom around the centre point of the screen rather than the centre point of the pane, particularly if the pane has been panned first. To do a zoom around a particular point you can use the Scale transformation provided as standard.

    Scale scale = new Scale();
    scale.setPivotX(pivotX);
    scale.setPivotY(pivotY);
    scale.setX(zoomFactorX);
    scale.setY(zoomFactorY);
    pane.getTransforms().add(scale);

The pivotX, pivotY point here is the point around which the scale takes place.  How, the problem comes to calculate the pivot point.  You can do this fairly easily using the position of the pane in the parent.

    Bounds bip = pane.boundsInParent().get();
    double pivotX = (screenWidth / 2 - bip.getMinX()) / scaleX;
    double pivotY = (screenHeight / 2 - bip.getMinY()) / scaleY;

    Scale scale = new Scale()
    ...

    scaleX *= zoomFactorX;
    scaleY *= zoomFactorY;

Where scaleX and scaleY are the current scaling.  You can keep track of the current scale easily enough by adjusting it after each zoom (as above) or you can get the current width / height from the bounds object and calculate the zoom from the original size.

For consistency, you can now use a transform to do the translation as well.  This makes no difference to the scaling and pivot calculation as the boundsInParent will still be the same whichever way the translation is done.

    Translate translate = new Translate(panX, panY);
    pane.getTransforms().add(translate);

JavaFX Layout Sizes

If you are using JavaFX then it is worth knowing that the definitive way to get size and position information for a Pane is to use

    Bounds bounds = pane.boundsInParent().get();

The Bounds object obtained gives width, height and translated position (minX, minY) for this pane in its parent.  Even if the width of a pane is set it may get overridden by the layout if there is insufficient room.  Therefore, you cannot rely on what you think the size is.  Instead use the bounds above to get the actual answer.



Wednesday, 30 January 2013

Maven Replacer Plugin

The replacer plugin allows files to be edited during a maven build.  This can be useful on generated classes so that the time stamp is removed or comments added.  Removing the timestamp means that the classes have no difference if the schema hasn't changed.  Without removing the timestamp classes will constantly look different and will require a check in to the cvs / subversion / tfs repository.

Example



    <plugin>
        <groupId>com.google.code.maven-replacer-plugin</groupId>
        <artifactId>replacer</artifactId>
        <version>1.5.2</version>
        <executions>
            <execution> 
                <phase>prepare-package</phase>
                <goals>
                    <goal>replace</goal>
                </goals>
            </execution>
        </executions>
        <configuration>                         
            <includes>                              
                <include>src/main/java/com/me/generated/**/*.java</include>            
            </includes>
            <replacements>
                <replacement>
                    <token>//${line.separator}// This file was generated by the JavaTM</token>
                    <value>//
// CSOFF: a.*
// This file was generated by the JavaTM</value>  
                </replacement>
                <replacement>
                    <token>^ \*/
@Xml</token>
                    <value> */
@SuppressWarnings("all")
@Xml</value>  
                </replacement>
                <replacement>
                    <token>^// Generated on.*$</token>
                    <value>// Generated on: [TEXT REMOVED by maven-replacer-plugin to avoid generating changes]</value>  
                </replacement>
            </replacements>                       
            <regexFlags>
                <regexFlag>MULTILINE</regexFlag>
            </regexFlags>
        </configuration>
    </plugin>

There are three replacement sections configured here.

1) Adding a comment at the top of the file.  In this case it is a CSOFF comment so that checkstyle doesn't check these generated classes but it could be a copyright comment or anything. Note the use of the ${line.separator} which means that this is still cross-platform compliant as the line separators are different for Windows compared with linux / unix.
2) The section replacement adds a PMD suppression just above the @Xml annotation.  This is similar to the checkstyle comment above but this works for PMD.  Again it could be used for other annotations or comments.
3) The third replacement is for getting rid of the generated date.  If this is run everytime the maven project is packaged then the classes will constantly look like they need a check in but only because the generated date has changed and not because the actual content of the class has changed.  By removing the date this problem is also removed.

This plugin could also be used for resources / properties etc.  It is a hugely useful plugin.  My only beef with it is that it seems hard to bind the plugin to any other goal other than package without Eclipse IDE getting confused and constantly rebuilding.

Monday, 7 January 2013

Glassfish Commands

Here are some useful glassfish commands

File structure

Glassfish has a weird file structure.  One installation everything is in

    c:/glassfish3/ 

but the actual default domain location is in

    c:/glassfish3/glassfish/domains

Other domains can be created in different locations to this and glassfish will only start the domain specified rather than starting all domains in a domain location.  This is glassfish's way of keeping separation between installations.  You can, of course, install multiple applications into a single domain.

In the commands below either the asadmin needs to be on the path or prefix the asadmin with <glassfish_home>/bin/.

Starting a Domain

To start a domain in the default location just do

    asadmin start-domain <domain_name>

if there is only one domain then the domain_name can be dropped.

Often it is useful to have domains installed in different locations.  To do this use

    asadmin start-domain --domaindir <domain_location> <domain_name>

Again if there is only one domain in the domain_location then the name can be dropped.

Stopping a Domain
The simple command to stop a running domain is

    asadmin stop-domain <domain_name>

If you are running a cluster you may need to do this bit first before stopping the individual domains.

    asadmin stop-cluster <cluster_name>

Creating a Domain

To create a new domain use the command

   asadmin --user admin --port 4848 --host localhost --interactive=true create-domain --domaindir <domain_location> --adminport 4848 --instanceport 8080  <domain_name>

Where domain_location and domain_name need to be completed.

Deleting a Domain

To delete a domain use

    asadmin delete-domain --domaindir <domain_location> <domain_name>

Thursday, 29 November 2012

Maven & xjc

Maven integration of xjc is available from a number of sources.  In this post I'll look at some examples of what is available from jvnet.

Documentation is available here: http://confluence.highsource.org/display/J2B/JAXB2+Basics+Plugins

Simple Example


    <plugin>
        <groupId>org.jvnet.jaxb2.maven2</groupId>
        <artifactId>maven-jaxb2-plugin</artifactId>
        <executions>
            <execution>    
                <goals>
                    <goal>generate</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <extension>true</extension>
           <schemaDirectory>src/main/resources</schemaDirectory>
           <schemaIncludes>
               <include>my_schema.xsd</include>
           </schemaIncludes>
            <generateDirectory>src/main/java</generateDirectory>
            <generatePackage>com.me.generated</generatePackage>
            <episode>false</episode>     
        </configuration>
    </plugin>

This simple example generates my_schema.xsd JAXB classes and puts them into src/main/java in the com.me.generated package.  This is pretty much the most simple example of this plugin.


Example With Catalogue File

    <plugin>
        <groupId>org.jvnet.jaxb2.maven2</groupId>
        <artifactId>maven-jaxb2-plugin</artifactId>
        <version>0.8.2</version>
        <executions>
            <execution>
                <goals>
                    <goal>generate</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <extension>true</extension>
            <generateDirectory>src/main/java</generateDirectory>

            <catalogs>
                <catalog>
                    <dependencyResource>            
                        <groupId>com.me.common</groupId>
                        <artifactId>xsd-project</artifactId>
                        <resource>common.catalog</resource>
                    </dependencyResource>
                </catalog>
            </catalogs>

            <episodes>
                <episode>
                    <groupId>com.me.common</groupId>
                    <artifactId>xsd-project</artifactId>
                </episode>
            </episodes>    

            <episode>true</episode> 

            <args>
                <arg>-XtoString</arg>
                <arg>-Xequals</arg>
                <arg>-XhashCode</arg>
            </args>
            <plugins>
                <plugin>
                    <groupId>org.jvnet.jaxb2_commons</groupId>
                    <artifactId>jaxb2-basics</artifactId>
                    <version>0.6.4</version>
                </plugin>
             </plugins>      
        </configuration>    
    </plugin>


This plugin will parse the available *.xsd files in the src/main/resources directory and create JAXB annotated classes in the src/main/java directory.  If an bindings.xjb is also present in the resources directory then this will be used.

generateDirectory - where to put the JAXB classes.
catalogs - These allow an xsd reference to be overridden and redirected locally or into a jar file.
episodes - This tells xjc to not create code for these xsd because it is already available.
episode - This tells xjc to generate an episode file for these xsds
args - optional arguments to add to the JAXB classes.  This requires the plugin that follows it.

Catalog File

A catalog file allows the xsd schema locations to be altered and redirected.  If a schema file has an import such as


    <xs:import namespace="http://www.me.com/common/config" />


Note there is no schemaLocation value.  This will fail the schema validation without a catalog file helping to tell xjc where the actual xsd source is.  A valid catalog file to do this would be

    PUBLIC "http://www.me.com/common/config" "maven:com.me.common:xsd-project!/config.xsd"

Here the first part of the catalog has the same namespace as the import namespace.  This is how they match. The second element can be a standard file location or, like here, a reference to an xsd in a jar which is a maven dependency.  It is only with the maven plugin that this maven:... reference will work.  Standard xjc does not recognise this notation. NOTE: there is a colon separating 'maven' from the groupId from the artifactId.  Putting a . instead will cause the catalogue redirect to not work and that can eat up time trying to find the reason why!!

Episode File

An episode file is just a standard bindings file.  It tells xjc not to create JAXB annotated classes for objects which may appear in an xsd (Not all the elements of the xsd need to be contained in an episode file although this would be a little unusual and require manually changing the episode file after generation).
This maven plugin can use episode files from other jars but can also be told to generate one using the

            <episode>true</episode> 

Common Errors

If you get a stack trace like this,


    com.sun.istack.SAXParseException2: SCD "x-schema::tns" didnt match any schema component

Then a schema is included in the episode file but never referenced.  If you can remove the episode file from the configuration then this will cure it.  Otherwise just create an empty schema which imports all the episode elements but does nothing with them.  I think this error is trying to be helpful and tell you when something is included and it doesn't need to be but the message isn't particularly clear.  Hopefully there may be an option to ignore this error in the future because an episode file may contain multiple schemas when you don't necessarily need them all.


Wednesday, 14 November 2012

XML Schemas / XSD

Here are a few simple memory joggers for how to create xml schema (xsd) files.

Namespaces

Namespaces are important parts of xsds.  They control the prefixes and help to remove ambiguity if there are two types which have the same name.  They are also import if you want to using binding files to create java classes in different packages for different files.

Normally a targetNamespace is defined for a schema along with a xmlns command which refers to the same targetNamespace.  The targetNamespace says that this xsd defines this namespace.  The xmlns is the same for all items but because it is the same as the targetNamespace it is satisfied by this file (it refers to itself so no import is needed).  The targetNamespace doesn't have to be included but makes it harder to extend or split up the schema later.


  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:conf="http://www.mycompany.com/myapp/config" targetNamespace="http://www.mycompany.com/myapp/config">


Note that the conf and targetNamespace are the same.

ComplexType

ComplexType is very common.  It defines a link between one object that can have multiple children.  An example of a ComplexType is

    <xs:complexType name="person">
        <xs:annotation>
            <xs:documentation>
                The details about a person.
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="FirstName" type="xs:string" minOccurs="1" maxOccurs="1" />
            <xs:element name="Surname" type="xs:string" minOccurs="1" maxOccurs="1" />
            <xs:element name="Age" type="xs:int" minOccurs="0" maxOccurs="1" />

        </xs:sequence>
    </xs:complexType>


The complexType can then be referenced in another object

    <xs:element name="staff" type="person" minOccurs="0" maxOccurs="unbounded" />

and in xml the person would look like

    <Person>
        <FirstName>Fred</FirstName>
        <Surname>Bloggs</Surname>
        <Age>43</Age>
    </Person>


Enumeration

If an enumeration is being used the don't make it an anonymous one.  If this happens then the xjc parser cannot turn it into a Java enumeration but instead does some horrible string effort.  Therefore, always make enumerations proper types.


    <xs:simpleType name="YesNo">
        <xs:annotation>
            <xs:documentation>Yes or No enumeration</xs:documentation>
        </xs:annotation>
        <xs:restriction base="xs:string">
            <xs:enumeration value="YES" />
            <xs:enumeration value="NO" />
        </xs:restriction>
    </xs:simpleType>


Restrictions need to have a 'base' that is the type of all the enumerations that it includes.

Extension

One object can extend another to include extra values.  For example, the person complexType defined about in the person object can be extended,

    <xs:complexType name="ExtendedPerson" >
        <xs:annotation>
            <xs:documentation>More people details</xs:documentation>
        </xs:annotation>
        <xs:complexContent>
            <xs:extension base="person">
                <xs:sequence>
                    <xs:element name="Salutation" type="SalutationType" minOccurs="1" maxOccurs="1" />
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>

Where SalutationType is another enumeration.  Once Java classes have been generated the ExtendedPerson class extends the Person class with salutationType being the only local variable.  So in xml

    <ExtendedPerson>
        <FirstName>Fred</FirstName>
        <Surname>Bloggs</Surname>
        <Age>43</Age>
        <SalutationType>MR</SalutationType>
    </ExtendedPerson>


Import

Sometimes it is useful to have an import from one schema into another.  This allows types to be used from different schemas.  Firstly include the xmlns for the right target into the schema header as follows,

    xmlns:com="http://www.mycompany.com/myapp/common" 

Then import a schemaLocation which tallies up to this namespace.  The import command is,

    <xs:import namespace="http://www.mycompany.com/myapp/common" schemaLocation="common.xsd"/>


Here the common.xsd must have a targetNamespace as the same as the namespace in the import statement, in this case 'http://www.mycompany.com/myapp/common'.

Binding Files

Binding files (.xjb) can be used to simplify the xjc command and create java objects in different target packages.  To use a binding file the different xsds must have different namespaces.  A binding file which allows different packages to be used could be,

    <jxb:bindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" >

        <jxb:bindings namespace="http://www.mycompany.com/myapp/common" schemaLocation="common.xsd" >
            <jxb:schemaBindings>
                <jxb:package name="com.mycompany.myapp.common"/>
            </jxb:schemaBindings>
        </jxb:bindings>
    
        <jxb:bindings namespace="http://www.mycompany.com/myapp/config" schemaLocation="config.xsd" >
            <jxb:schemaBindings>
                <jxb:package name="com.mycompany.myapp.config"/>
            </jxb:schemaBindings>
        </jxb:bindings>
    </jxb:bindings>

The binding file can be referenced using the -b command in xjc.

GlobalBindings

It is possible to have a bespoke element that needs to be parsed in a particular way.  This can be done with a globalBinding such as,

    <jxb:globalBindings fixedAttributeAsConstantProperty="true">
        <jxb:javaType name="com.my.SpecialElement" xmlType="my:specialElement"
                      parseMethod="com.my.SpecialElementAdaptor.unmarshal"
                      printMethod="com.my.SpecialElementAdaptor.marshal">
        </jxb:javaType>
    </jxb:globalBindings>

This can also be used to format standard types such as dates, although this will be global across all the schemas and will result in xjc creating Adaptors in weird packages!

    <jxb:globalBindings fixedAttributeAsConstantProperty="true">
        <jxb:javaType name="java.util.Date" xmlType="xs:dateTime"
                      parseMethod="com.my.DateTimeAdaptor.unmarshal"
                      printMethod="com.my.DateTimeAdaptor.marshal">
        </jxb:javaType>
    </jxb:globalBindings>

SchemaBindings

In the situation where there are multiple schemas in a binding file this globalBinding is unlikely to be good enough (or even work at all).  Therefore, the binding can also be included in the schema part so that the binding only applies to one schema.

    <jxb:bindings namespace="http://www.my.com/common" schemaLocation="common.xsd" >
        <jxb:schemaBindings>
            <jxb:package name="com.my.common.generated"/>
        </jxb:schemaBindings>
        <jxb:bindings node="//xs:simpleType[@name='DeletionDateTime']">  
            <jxb:javaType name="java.util.Date"
  parseMethod="com.my.DateTimeAdaptor.unmarshal"
  printMethod="com.my.DateTimeAdaptor.marshal"/>  
        </jxb:bindings>
    </jxb:bindings>

This form uses an xPath to find the correct simpleType.

    node="//xs:simpleType[@name='DeletionDateTime']"

Note that // means search everywhere in the document for a xs:simpleType with name 'DeletionDateTime'.

Both the GlobalBindings and the SchemaBindings create Adaptors which are just named Adaptor#.  This can cause name clashes when you have a hierarchy of projects (jars) which means that you can end up not using the correct adaptor.

XJC Extension & Adaptors

A further option to allow a specific adaptor to be used is to specify the adaptor that you want to use.  This can be done using the xjc extension.  Firstly you need to include the namespace in the bindings file.
    <jxb:bindings  version="2.1" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" 
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">

Next you can then use the xjc options.

    <jxb:bindings namespace="http://com.my/data" schemaLocation="my-data.xsd">
        <jxb:schemaBindings>
            <jxb:package name="com.my.data.generated" />
        </jxb:schemaBindings>
        
        <jxb:bindings node="//xs:complexType[@name='_Name_']/xs:sequence/xs:element[@name='_Date_']">
            <xjc:javaType name="org.joda.time.DateTime" adapter="com.my.data.util.JodaDateAdaptor" />    
        </jxb:bindings>
    </jxb:bindings>

xjc

xjc is bundled with java and is used to parse xsd and xjb files to create JAXB annotated java classes for a particular xml schema.  Example commands are

To parse a single file

    xjc -d myapp/java -p com.mycompany.myapp config.xsd

To parse multiple files

    xjc -d myapp/java -p com.mycompany.myapp *.xsd

To parse multiple files using a binding

    xjc -d myapp/java -b myapp.xjb *.xsd

-d = The route directory to create the classes in
-p = The package from the route directory
-b = refer to a binding file