A basic introduction to Java events
What is a Java event?
An event generally occurs when the state of a Java object (also known as a component) changes. The Java object in which this state has changed is called the event source object. Sometimes, other Java objects need to be informed of this change. In order to inform these other Java objects, the event source object needs to know who is interested in its state change. Therefore, the other Java objects register themselves by the event source object to get informed when a change occurs in the event source object. The other Java objects all become an event listener of the event source object. When a state change occurs, the event source object knows which event listeners to inform about the change. To inform the event listeners about the change, an event object is needed to tell what has changed exactly - it will contain information about the event. The process of sending an event object from the event source to the event listeners is called: firing the event. The event listeners must handle this fired event using a special method named an event handler. Each event listener handles the fired event for its own purpose. This means that each event listener can react differently on the received event object.
TODO mention event listener interface also
Figure 1: the communication process between components
The event source, the event listeners and the event object itself form the communication process to signal the change from one component to any other component(s). Figure 1 illustrates this principle. This is in a nutshell what Java events are and do.
What you should know about Java events
A general misconception about Java events is that they are only used for programming user interfaces, like Java Swing. This is an erroneous assumption which has spread among a lot of Java developers. It is absolutely wrong to say that Java events are only used for GUI programming!
The purpose of an event source is to inform an event listener object that something has happened to the event source object. The event object includes all of the information that a listener needs to figure out what happened and to which event source object it happened.
The event listener interface is the contract between the listener objects and the event source object. The contract provides the event source with the method to call when it fires the event.
The event source object keeps an internal administration of all registered event listeners and provides a mechanism to add and remove listeners from its listener administration. In other words: each listener that registers itself with a certain event source object to receive fired events, can also de-register itself from this event source object and thus no longer receive fired events.
The event object that is sent, is immutable (e.g. cannot be changed by other objects) because the event source object shares the same event object among all the event listeners.
To listen for an event, an event listener must implement the listener interface and register itself with the event source object of interest.
Working with the JsaPar library events
The JsaPar API for receiving Java events
- discuss API part of the library
- use org.jsapar.ParsingEventListener
- Callback events while parsing to be able to handle huge files without loading everything into memory.
For very large files there can be a problem to build the complete org.jsapar.Document in the memory before further processing. It may simply take up to much memory. In that case you may choose to get an event for each line that is parsed instead. You do that by registering a sub-class of org.jsapar.ParsingEventListener to the org.jsapar.input.Parser. That way you can process one line at a time, thus freeing memory as you go along.
The JsaPar library makes use or its own custom Java events using the Delegation Event Model in Java. The reason why the library fires Java events is because of the low memory footprint that the library consumes when processing huge data sources (in the magnitude of Gigabytes). If the library would process these large data sources by loading them completely into memory using a Document object while parsing, the library would consume too much memory to hold all processed Line objects of these data sources and would eventually slow down an operating system to the extend that it becomes inoperative to function normally. This is of course prevented by the memory management rules of the Java Virtual Machine and the operating system itself, but nevertheless it makes the library quantifiable for 'defective software' or in developers tongue: poorly written code.
When the JsaPar library user wants to process large data sources, the only option is to use the Java event mechanism to process these kind of data sources. That means two things: the JsaPar library user has to have knowledge of the event mechanism in order to handle these events within its own client code and the user needs to know what he/she is doing. How it works. Writes his own handler.
Working with JsaPar events has its pros and cons. One of these pros is that you can use the JsaPar library to work with very large files without any limits. This is because of the low memory footprint that the JsaPar library consumes when processing really large files. Even with files that are several gigabytes large the library can parse and generate these huge files without consuming more than a few kBytes of memory. One of the cons is that the client code becomes somewhat more complex, so that developers with an entry level Java knowledge do not fully comprehend how the code works. On the other hand, if you really need a low memory footprint and have to process huge files, there is no better alternative than to work with the JsaPar events.
The event mechanism in Java gives the developer an unique way of signalling the client code
How events are handled within the JsaPar library.
Dealing with JsaPar events within your own code.
How to work with JsaPar events
Events for each line