Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Receive events from XMLBeans

Customize XMLBean POJOs to notify observers of changes to your data model

Jacob D. Eisinger (jeising@us.ibm.com), Staff Software Engineer, IBM
Photo of Jacob Eisinger
Jacob Eisinger currently works on the next-generation service-oriented architecture (SOA) technologies in Software Group Strategy, Emerging Standards at IBM. He has expertise in Web services, XML, Java, and brewing beer. Oh, and he loves Hokie football.
Vince C. Brunssen (brunssen@us.ibm.com), Advisory Software Engineer, IBM
Photo of Vince Brunssen
Vince Brunssen is currently leading prototypes on the latest Web service specifications as they're released. He's in Software Group Strategy, Emerging Standards at IBM. Throughout his career, he's run the gambit on technologies, from the user experience on Eclipse to the back end with Universal Description, Discovery, and Integration (UDDI). Vince also golfs, and he is really, really good at that, too!

Summary:  XMLBeans is a great XML-to-Java™ data-binding technology, but it lacks the ability to register observers for model changes. However, you can customize generated plain old Java objects (POJOs) to include the necessary interfaces and the notification of changes. Create a Sudoku Rich Client Platform (RCP) game application in Eclipse, and learn how to use eventing to validate the user's input.

Date:  29 Jan 2008
Level:  Intermediate
Also available in:   Chinese  Russian  Japanese

Activity:  16961 views
Comments:  

XML Schema describes the types, elements, and structures of XML. However, generic tools such as Simple API for XML (SAX), Document Object Model (DOM), and XML Object Model (XOM) make it difficult to use the information quickly. XMLBeans is a data-binding framework that creates POJOs from an XML Schema, allowing you to read, manipulate, and write XML quickly.

When working with POJOs, especially thick clients, you need to know when the object changes—something commonly referred to as eventing or notification. Eventing is a core component of the Model View Controller (MVC) and Model 2 paradigm, which stresses the decoupling of graphical user interface (GUI) code from the model code. By using a Sudoku game as an example, we'll show you how to easily add eventing to XML-based Java applications with XMLBeans extensions.

Sudoku is a nine-by-nine grid divided into nine three-by-three subgrids. The game starts with a few of the cells already filled in with numbers ranging from 1 to 9. The player's job is to fill in the rest of the cells based on the following constraints:

  1. All cells must contain one number between 1 and 9. This is handled by the XMLBeans generated code.
  2. All nine cells within each row must be unique.
  3. All nine cells within each column must be unique.
  4. All nine cells within each subgrid must be unique.

Figure 1 shows a view of the board. We've developed an application that uses XMLBeans eventing to validate if constraints 2-4 are being met. If a constraint is not met, the view is updated to show the conflicting cells in red.


Figure 1. Sample Sudoku game board
Sample Sudoku game board

For more information on the history and strategies of Sudoku, see Resources.

Process flow overview

The Observer design pattern allows interested parties to be notified of changes. The XMLBeans eventing code described in this article is an instance of this design pattern. The idea is to allow objects to register for model changes in an XmlObject at run time. This way, you can attach listeners to Sudoku cells to enable validation on every change.

XMLBeans lets you use a configuration file, also known as the XSDCONFIG file, to customize the code generation. The XSDCONFIG file contains XML configuration for:

  1. Namespace mapping to a Java package
  2. Type and element QName mapping to a Java class
  3. Adding methods to generated code
  4. Adding implementation before and after a model changes

Item 4 allows for eventing to occur for interested parties if the interested parties are known at compile time. Unfortunately, this is not always the case. For more information on the contents of the XSDCONFIG file, see Resources.

To enable eventing, you need to implement items 3 and 4. You do this by following these four steps:

  1. Write an interface extension to allow for listeners to be registered to XmlObjects.
  2. Write a PrePostSet extension that notifies the listeners of a model change.
  3. Create an XSDCONFIG file with the necessary configuration information.
  4. Tell the XMLBeans utility scomp about the XSDCONFIG file.

Write an interface extension

The interface extension feature of XMLBeans allows you to add methods with custom implementation for the generated POJOs. XMLBeans requires you to create an interface and a static implementation for each method in that interface. The interface that we created is located in com.ibm.wsrc.xmlbeans.IModelChangeEmitter and contains four methods, as shown in Listing 1.


Listing 1. com.ibm.wsrc.xmlbeans.IModelChangeEmitter.java
                
public interface IModelChangeEmitter {
  public void fireModelChangeEvent(ModelChangeEvent event);
  public void addModelChangeListener(IModelChangeListener modelChangeListener);
  public void removeModelChangeListener(IModelChangeListener modelChangeListener);
  public boolean hasModelChangeListeners();
}

Additional IModelChangeEmitter method

If needed, you can add a second inspection to method, IModelChangeEmitter, to retrieve the list of listeners registered.

The interface has two life cycle management listener methods, addModelChangeListener() and removeModelChangeListener(); one inspection of listeners, hasModelChangeListeners(); and one utility method, fireModelChangeEvent(), which is used to notify all registered listeners of a model change.

When any process calls one of these methods, XMLBeans passes the XmlObject that the method was called on and the parameters to a static implementation. In this case, the static implementation is in com.ibm.xmlbeans.eventing.ModelChangeEmitterHandler.java. Since this is a static implementation and you cannot store instance variables in XmlObjects, you need to store the list of interested parties elsewhere. In this implementation, the list is stored in a static HashMap. Listing 2 shows which Java code contents are stored in the class.


Listing 2. com.ibm.wsrc.xmlbeans.ModelChangeEmitterHandler.java
                
public class ModelChangeEmitterHandler {
  private static HashMap<XmlObject, LinkedList<IModelChangeListener>> listeners =
    new HashMap<XmlObject, LinkedList<IModelChangeListener>>();

  public static void fireModelChangeEvent(XmlObject xo, ModelChangeEvent event) {
    LinkedList<IModelChangeListener> list = listeners.get(xo);
    if (list == null)
      return;

    for (IModelChangeListener listener : list)
      listener.modelChange(event);
  }

  public static void addModelChangeListener(XmlObject xo,
    IModelChangeListener modelChangeListener) {
    LinkedList<IModelChangeListener> list = listeners.get(xo);
    if (list == null) {
      list = new LinkedList<IModelChangeListener>();
      listeners.put(xo, list);
    }
    list.add(modelChangeListener);
  }

  public static void removeModelChangeListener(XmlObject xo,
    IModelChangeListener modelChangeListener) {
    LinkedList<IModelChangeListener> list = listeners.get(xo);
    if (list == null)
      return;
    list.remove(modelChangeListener);

    // remove references of list and XmlObject
    if (list.isEmpty())
      listeners.remove(xo);
  }

  public static boolean hasModelChangeListeners(XmlObject xo) {
    return listeners.containsKey(xo);
  }
}

The addModelChangeListener() code is a good example of how the listener list is utilized. The addModelChangeListener() method first checks to see if a listener list is registered for the XmlObject, then creates it if it doesn't exist already. Finally, it adds the listener to the list.


Write a PrePostSet extension

The PrePostSet extension lets you add custom processing to XMLBeans. You use a static class that has methods that run before and after the XmlObject changes, as shown in Listing 3.


Listing 3. PrePostSet extension pseudocode
                
if (PrePostSetExtension.preSet())
  updateXmlObject();
PrePostSetExtension.postSet();

The static methods, preSet() and postSet(), both have the same signature: *Set(int opType, XmlObject xo, QName propertyName, boolean isAttr, int index). At first glance, it appears that the postSet() method is where all of the eventing code would live. However, the postSet() method does not have all of the information needed to fire an event. The postSet() needs to fire an event to all of the registered listeners with the object being updated, the action of the update, the value before, and the value now. The previous value is not known in the postSet() function. Therefore, you need to store the contents of the previous object statically.

The previous values are stored in a static HashMap called oldValues. On the preSet() method, the old value is copied into this HashMap, and on the postSet() method, the actual firing of the event is performed. Listing 4 shows what the preSet() method looks like.


Listing 4. com.ibm.xmlbeans.eventing.ModelChangePrePostHandler.preSet()
                
public static boolean preSet(int opType, XmlObject xo, QName propertyName,
  boolean isAttr, int index) {
  IModelChangeEmitter emitter = (IModelChangeEmitter)xo;
  if (!emitter.hasModelChangeListeners())
    return true;

  // get the child that will be changed
  XmlObject oldXO = null;
  if (isAttr)
    oldXO = xo.selectAttribute(propertyName);
  else {
    switch (opType) {
      case PrePostExtension.OPERATION_SET:
      case PrePostExtension.OPERATION_REMOVE:
        oldXO = getChildXO(xo, propertyName, index);
        break;
      case PrePostExtension.OPERATION_INSERT:
        break;
    }
  }

  // store the old value
  int hash = hashCode(xo, propertyName, isAttr, index);
  Object oldValue = null;
  if (oldXO == null)
    oldValue = null;
  else if (oldXO instanceof SimpleValue) {
    oldValue = ((SimpleValue)oldXO).getObjectValue();
    if (oldValue instanceof XmlObject)
      oldValue = ((XmlObject)oldValue).copy();
    } else
      oldValue = oldXO.copy();

  oldValues.put(hash, oldValue);

  return true;
}

In this method, the code inspects the model object to see if it has any listeners attached. If listeners are attached, the current property value is cached. The utility method getChildXO() is called if it is not an attribute. Finally, this value is copied if it is a non-constant XmlObject. Either this copy or the original is then stored in the oldValues HashMap. Listing 5 shows the postSet() method.


Listing 5. com.ibm.xmlbeans.eventing.ModelChangePrePostHandler.postSet()
                
public static boolean postSet(int opType, XmlObject xo, QName propertyName,
  boolean isAttr, int index) {
  IModelChangeEmitter emitter = (IModelChangeEmitter)xo;
  if (!emitter.hasModelChangeListeners())
    return true;

  // get the old value;
  int hash = hashCode(xo, propertyName, isAttr, index);
  Object oldValue = oldValues.get(hash);
  oldValues.remove(hash);

  ModelChangeEvent.Action action = ModelChangeEvent.Action.UPDATE;

  // get the new xml object
  XmlObject newXO = null;
  if (isAttr)
    newXO = xo.selectAttribute(propertyName);
  else {
    switch (opType) {
      case PrePostExtension.OPERATION_SET:
        newXO = getChildXO(xo, propertyName, index);
        break;
      case PrePostExtension.OPERATION_INSERT:
        XmlObject[] children = xo.selectChildren(propertyName);

        // on an insert, it is always the last element
        newXO = children[children.length - 1];
        action = ModelChangeEvent.Action.CREATE;
        break;
      case PrePostExtension.OPERATION_REMOVE:
        action = ModelChangeEvent.Action.DELETE;
        break;
    }
  }

  // get the new value
  Object newValue = null;
  if (newXO == null)
    newValue = null;
  else if (newXO instanceof SimpleValue)
    newValue = ((SimpleValue)newXO).getObjectValue();
  else
    newValue = newXO;

  // if newValue != oldValue
  if (((newValue == null) && (oldValue != null)) || ((newValue != null)
    && (!newValue.equals(oldValue))))
    emitter.fireModelChangeEvent(new ModelChangeEvent(propertyName,
      emitter, oldValue, newValue, action, index));
  return true;
}

The postSet() method first checks to see if any listeners are attached to this XmlObject. If there are interested parties, the code retrieves the old value from the oldValues HashMap. It retrieves the current value from the current XmlObject and assigns it to the newValue variable. Finally, postSet() checks the oldValue to ensure that it is not equal to the newValue. The XmlObject creates and fires a model change event. Listing 6 shows the utility methods.


Listing 6. com.ibm.xmlbeans.eventing.ModelChangePrePostHandler utility methods
                
private static XmlObject getChildXO(XmlObject xo, QName propertyName, int index) {
  XmlObject childXO = null;
  XmlObject[] values = xo.selectChildren(propertyName);
  if (values.length != 0) {
    if (index == -1)
      childXO = values[0];
    else if (index < values.length)
      childXO = values[index];
  }
  return childXO;
}

private static int hashCode(XmlObject xo, QName propertyName, boolean isAttr, int index) {
  final int prime = 31;
  int result = 1;
  result = prime * result + index;
  result = prime * result + (isAttr ? 1231 : 1237);
  result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode());
  result = prime * result + ((xo == null) ? 0 : xo.hashCode());
  return result;
}

The getChildXO() method retrieves a property value from the XmlObject. It uses the selectChildren() method and then grabs the right child if more than one is returned. The hashCode() method calculates a unique hash for an XmlObject and the property of the XmlObject; Eclipse creates the method automatically.


Configure XMLBeans generation

To implement eventing on top of XMLBeans, you need to use and configure the interface extension feature and the PrePostSet extension feature. Listing 7 shows what the XSDCONFIG file looks like.


Listing 7. XSDCONFIG for XMLBeans eventing
                
<xb:config xmlns:xb="http://xml.apache.org/xmlbeans/2004/02/xbean/config">
  <xb:extension for="*">
    <xb:interface name="com.ibm.xmlbeans.eventing.IModelChangeEmitter">
      <xb:staticHandler>
        com.ibm.xmlbeans.eventing.ModelChangeEmitterHandler
      </xb:staticHandler>
    </xb:interface>
  </xb:extension>

  <xb:extension for="*">
    <xb:prePostSet>
      <xb:staticHandler>
        com.ibm.xmlbeans.eventing.ModelChangePrePostHandler
      </xb:staticHandler>
    </xb:prePostSet>
  </xb:extension>
</xb:config>

The first xb:extension element of xb:config contains the configuration of the interface extension. Here it defines the interface for all generated XmlObject instances to extend IModeChangeEmitter. XMLBeans will run the implementation in ModelChangeEmitterHandler.

The second xb:extension element of xb:config contains the configuration for the PrePostSet extension. It configures XMLBeans to call preSet() and postSet() in the ModelChangePrePostHandler class before and after a process modifies a property.

Finally, to input the configuration file to the generator, you specify the XSDCONFIG file as the last parameter to scomp. For the Sudoku game, you specify this in a Java class, as shown in Listing 8.


Listing 8. com.ibm.xmlbeans.generator.SudokuSchemaGenerator.java
                
public class SudokuSchemaGenerator {
  public static void main(String[] args) {
    String[] xmlBeanArgs = new String[] {
      "-d", "xb_bin",
      "-src", "xb_src",
      "-out", "lib/sudokuXB.jar",
      "-javasource", "1.5",
      "schema/sudokuXBE.xsd",
      "schema/eventing.xsdconfig"
    };
    org.apache.xmlbeans.impl.tool.SchemaCompiler.main(xmlBeanArgs);
  }
}

For more information on scomp and the command-line arguments, see Resources.

After running this command, you now have POJOs from sudokuXBE.xsd that allow for interested parties to be notified when the POJOs change.


Create the Sudoku game RCP application

The Sudoku game is an RCP application that notifies users when a cell has a bad value. The values are validated against the other cells in the row, column, and subgrid. If any of these values conflict, the offending cells will turn red, as shown in Figure 2.


Figure 2. The Sudoku game in action
Two screenshots of the Sudoku game in action.

Take the following steps to implement the game's user interface (UI):

  1. Create a Sudoku schema that represents the game board.
  2. From the schema, generate a set of XMLBeans with eventing.
  3. Using the generated XMLBeans with eventing, create an MVC-style application.

The general design of the application is to remove the coupling of the view from the model. The controller, which is the Standard Widget Toolkit (SWT) key listener, first modifies the model. The model then notifies the validators of the change. The affected validators check to see if the cell they control is still valid; if it is, they flip the valid flag if needed. This flip causes the framework to fire another event, which the view (cell) catches. This updates the background color of the cell. Figure 3 shows these four steps in a flow chart.


Figure 3. Event flow through the Sudoku RCP application
Event flow through the Sudoku RCP application

Model the Sudoku game in XML Schema

The overall schema definition is simple and starts with the concept of the game board. The game board contains nine rows and nine columns of cells that can only contain a value of 1 through 9. Use this simple definition to create the schema. The board type shown in Figure 4 consists of exactly nine row type elements. This is sufficient enough to define the overall nine-by-nine Sudoku grid.


Figure 4. BoardType XML schema type
BoardType XML Schema type

You can further describe the board by defining a row type, as shown in Figure 5.


Figure 5. RowType XML schema type
RowType XML Schema type

The row type contains exactly nine cell type elements. By dividing the row type down to nine cell types, you can get the granularity needed to define the values that are in each cell of the row, as shown in Figure 6.


Figure 6. CellType XML schema type
CellType XML Schema type

The cell type is a simple element that can contain a range of values from 1 to 9 and a period (.) that represents no value. The cell type also has an attribute that represents whether the cell is valid based on the row, column, and grid requirements, as shown in Figure 7.


Figure 7. CellStringType XML schema type
CellStringType XML Schema type

The cell string type further defines the cell by enforcing the constraint that a cell can only contain a value of 1 through 9 and a period.

Generate XMLBeans

Using this schema definition and the XMLBeans generation code as defined in Configure XMLBeans generation, you've now produced a set of POJOs that represent the schema and also contain the eventing model so that the UI can be notified of any changes to the model.

Write the application UI

You write the UI in a classic MVC style that's made possible by the eventing that is a part of the generated XMLBeans. The view of the model was developed using the Eclipse platform to create an RCP application. The RCP application is essentially an Eclipse plug-in, and as a part of the startup of the Eclipse plug-in, a view is initialized. As you create each SWT text widget and add it to the view, you add a key listener through the text.addKeyListener() method call. This allows you to intercept the key presses as the user enters values into blank cells. See Listing 9.


Listing 9. com.ibm.xmlbeans.tutorial.View.addKeyListeners().new KeyAdapter() {...}
                
public void keyPressed(KeyEvent e) {
  switch (e.keyCode) {
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      if (text.getEditable()) {
        final CellStringType.Enum newValue =
          CellStringType.Enum.forString(String.valueOf(e.character));
        Job job = new Job("Run Validation") {
          protected IStatus run(IProgressMonitor arg0) {
            XbeUtilities.getCell(Activator.getDefault().getBoard(), myRow, myCol)
              .setCellValue(newValue);
            return Status.OK_STATUS;
          }
        };
        text.setText(String.valueOf(e.character));
        job.schedule();
      }
      break;
    case SWT.BS:
    case SWT.DEL:
    case '.':
    case ' ':
      if (text.getEditable()) {
        Job job = new Job("Run Validation") {
          protected IStatus run(IProgressMonitor arg0) {
            XbeUtilities.getCell(Activator.getDefault().getBoard(), myRow, myCol)
              .setCellValue(CellStringType.X);
            return Status.OK_STATUS;
          }
        };
        job.schedule();
        text.setText(" ");
      }
      break;
    // ... arrow navigation code ...
  }
  e.doit = false;
}

You then set the value in to the model through the setCellValue(newValue) call. By making this call, you update the model that is defined in XML by the schema. XMLBeans eventing code fires an event that notifies all listeners that the model has changed.

A key part of the eventing model is the notification of a cell's validity based on its position within a row, column, or three-by-three subgrid. From within the modelChange(ModelChangeEvent event) method, you call the runValidation() method to validate the cell, as shown in Listing 10.


Listing 10. com.ibm.xmlbeans.listeners.CellValidatorListener.modelChange(ModelChangeEvent)
                
public void modelChange(ModelChangeEvent event) {
  if (XbeUtilities.CELLVALUE_QNAME.equals(event.getPropertyName())) {
    // if the current cell value is set
    if (!CellStringType.X.equals(cell.getCellValue())) {
      if (cell.equals(event.getSource())) {
        // run manual validation
        int count = runValidation();
        numInvalid = count;
      } else {
        // another cell
        if (cell.getCellValue().equals(CellStringType.Enum.forString(
          (String)event.getNewValue())))
          numInvalid++;
        else {
          if (cell.getCellValue().equals(CellStringType.Enum.forString(
            (String)event.getOldValue())))
            numInvalid--;
        }
      }
  } else if (cell.equals(event.getSource()))
    numInvalid = 0;

  if (numInvalid == 0)
    cell.setValid(true);
  else if (numInvalid < 0) {
    Activator.getDefault().getLog().log(
      new Status(IStatus.WARNING, Activator.PLUGIN_ID,
      "Cell validator has a negative number of invalid cells.  This is impossible."));
  } else
    cell.setValid(false);
  }
}

As you can see, you first check which property has changed. In Listing 10, it is the CELLVALUE_QNAME property. If the cell is the event source, then you call runValidation() to validate against all criteria. However, if it is another cell, then you just need to verify that the values are not equal to the new value. If they are, then you need to increment the numInvalid count by one. If it is equal to the old value, then you need to decrease the numInvalid by one. Finally, if numInvalid is zero, then you can set the cell's valid flag to true through cell.setValid(true). Otherwise, you need to set the cell's valid flag to false through cell.setValid(false). When you set the valid flag on the cell through these calls, XMLBeans eventing fires another event. This event is processed by a view listener to update the border color of the cell, as shown in Listing 11.


Listing 11. com.ibm.xmlbeans.tutorial.View.addTextNotifier(...).new IModelChangeListener() {...}.modelChange(ModelChangeEvent)
                
public void modelChange(ModelChangeEvent event) {
  if (XbeUtilities.VALID_QNAME.equals(event.getPropertyName())) {
    // might not be in the display thread, need to run in it to
    // modify the background!
    text.getDisplay().asyncExec(new Runnable() {
      public void run() {
        if (cell.getValid())
          text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_WHITE));
        else
          text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED));
      }
    });
  }
}

As you can see, when the modelChange event is fired, the cell gets notified because you added modelChangeListener() to each cell. When the event is processed, the cell checks to see if it's valid and sets the background color of its corresponding text widget appropriately.


Conclusion

Through the use of eventing, you can use a simplified coding model to remove the dependency of the model on the user interface. This allows you to create the Sudoku game application quickly and without coupling the view to the model.

Through the use of two extension points in XMLBeans—the interface and PrePostSet—you can add eventing to XMLBeans. You use the interface extension to add listeners to XMLBeans, and you use the PrePostSet extension to capture the changes and notify the interested parties of the change. Finally, you integrate these extensions into XMLBeans generation through a configuration file.



Downloads

DescriptionNameSizeDownload method
XMLBeans eventing with Sudoku game Eclipse projectx-xmlbeanse/SudokuProject.zip2694KB HTTP
Sudoku boards described in XMLx-xmlbeanse/SudokuBoards.zip4KB HTTP
Sudoku game compiled for Windowsx-xmlbeanse/SudokuApplication-Win32.zip146346KB HTTP

Information about download methods


Resources

Learn

  • The Apache XMLBeans site: Get documentation and download information on XMLBeans so you can access XML by binding it to Java types.

  • The Extension Interfaces Feature page: Visit the XMLBeans wiki for information on extending XMLBeans generated code.

  • The PrePostSetFeature page in the XMLBeans wiki: Explore how to invoke code on model changes for generated XmlObjects.

  • The Use XForms to create your own Sudoku game series (Nicholas Chase, developerWorks, February 2007): Learn to make a Sudoku game in XForms.

  • Programming With XMLBeans (Abhinav Chopra, developerWorks, September 2004): Dig into this introduction to XMLBeans and see how XMLBeans revolutionizes data binding.

  • The XMLBeans install guide: Find the environment variables and other setup information you need to run XMLBeans.

  • Sudoku: Read about the history of Sudoku and strategies in this Wikipedia article.

  • Configuring XMLBeans (Hetal Shah, Dev2Dev, November 2004): Learn to use XSDCONFIG to alter the code generation by XMLBeans.

  • Observer pattern: In this Wikipedia article, read about the design pattern implemented by the XMLBeans eventing code.

  • scomp: Read the documentation on the command-line arguments for the schema compiler and code generator.

  • IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.

  • XML technical library: See the developerWorks XML Zone for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.

  • developerWorks technical events and webcasts: Stay current with technology in these sessions.

  • The technology bookstore: Browse for books on these and other technical topics.

Get products and technologies

  • IBM trial software: Build your next development project with trial software available for download directly from developerWorks.

Discuss

About the authors

Photo of Jacob Eisinger

Jacob Eisinger currently works on the next-generation service-oriented architecture (SOA) technologies in Software Group Strategy, Emerging Standards at IBM. He has expertise in Web services, XML, Java, and brewing beer. Oh, and he loves Hokie football.

Photo of Vince Brunssen

Vince Brunssen is currently leading prototypes on the latest Web service specifications as they're released. He's in Software Group Strategy, Emerging Standards at IBM. Throughout his career, he's run the gambit on technologies, from the user experience on Eclipse to the back end with Universal Description, Discovery, and Integration (UDDI). Vince also golfs, and he is really, really good at that, too!

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Java technology, Open source
ArticleID=281452
ArticleTitle=Receive events from XMLBeans
publish-date=01292008
author1-email=jeising@us.ibm.com
author1-email-cc=dwxed@us.ibm.com
author2-email=brunssen@us.ibm.com
author2-email-cc=dwxed@us.ibm.com