Jettison is a library that provides a streaming parser for the JSON data format. Reading that sentence again makes you want to compare it to Stax, the streaming parser for XML. Jettison provides implementation classes that inherit from the same interfaces that a caller would use for XML reading / writing. Diving into some code reveals how JSON is written using this API…
public void go()
{
try
{
MappedNamespaceConvention con = new MappedNamespaceConvention();
XMLStreamWriter writer = new MappedXMLStreamWriter(con, new PrintWriter(System.out));
writer.writeStartDocument();
writer.writeStartElement("alice");
writer.writeCharacters("bob");
writer.writeEndElement();
writer.writeEndDocument();
writer.flush();
writer.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
Output: {“alice”:”bob”}
Notice that the XMLStreamWriter is the one in the javax.xml.stream package. The underlying data format that is written using this interface is abstracted. You could use the XMLStreamWriter to write a XML document for example. A XMLStreamReader can be used in the same way to read a XML or JSON document.
Every once in a while, there comes a need to convert an OutputStream into an Inputstream. The PipedInputStream and PipedOutPutstream classes allow one to achieve this. The idea behind the piped stream is that at one end of the pipe, a writer thread writes to a PipedOutputStream. A PipedInputStream thread concurrently reads whatever is written on the other side. Here is an example use case…
Assume that a thread streams random words and another thread needs to read these words and write them to System.out. Lets call the producer of the words, a DataSource, and the client the DataConsumer (which is the consumer of the producer). The DataConsumer has a problem. Some of the words from the DataSource are deemed inappropriate by the DataConsumer. The consumer would rather receive ‘***’ than the inappropriate word.
Any system that logs vast amounts of information, needs to think about performance. The activity of logging cannot be a synchronous blocking call that returns only when the message has been logged to a persistence store. Enterprise logging systems usually make use of a message bus to carry messages asynchronously to their target persistence store. Be it a database or a file.
Talking about logging brings us to System.out.println() (Lets call is SOP for short). It is a surprisingly commonly method to “log” messages. SOP is not meant to be used as a logging system, but unfortunately there is no dearth of projects that have these statements scattered around the code base. The adverse effects that this statement can bring on the performance of the system is often not recognized as well as it should be.
Why is SOP a bottleneck for performance ? This is why…
While coming up with APIs or a framework, design forms a crucial part of the end result. While a solid design does indeed allow for flexible usage of an API, usability goes hand in hand with the design. What better way is there to create an API, than to learn from the mistakes and successes of other developers first ? Lets take a look at some examples in the java API where things could have been better…
Stack and Properties:
A java.util.Stack provides a standard Stack implementation in the java language. But did you know it extend a java.util.Vector ? Why is this wrong ? Because you can do this
package com.design;
import java.util.Stack;
import java.util.Vector;
public class StackTests
{
public static void main(String... args)
{
new StackTests().go();
}
public void go()
{
Vector<String> vector = new Stack<String>();
vector.add("first");
Stack <String> stack = (Stack <String>) vector;
String peek = stack.peek();
System.out.println(peek);
stack.push("next");
stack.push("item");
String remove = vector.remove(2);
System.out.println("Removed: " + remove);
peek = stack.peek();
System.out.println(peek);
}
}
Output:
first
Removed: item
next
There are so many things that are going on there that are wrong.
- Vector is a slow DS. Its methods are synchronized and there is no way around this right now since this contract has been sealed. It cannot be changed without changing backward compatibility.
This has been a sad week for java. One of the string of bad things happening to it, is the abandonement by Mac OS X. Among the interesting thoughts that have been thrown out there for a possible rescue plan, this one seemed to stand out.
In a nutshell, the link points to a post by Adam-Bien suggesting that users might pay for a JVM on the Mac, thereby opening up a business opportunity. That might be far fetched considering
- Apple wants to be a control freak of sorts. Anything that is not objective-C is a target
- Folks usually have a very hard time convincing themselves to pay for something that they used to get for free.
- It would be pretty difficult to write a JVM targeted for the Mac from scratch, given that many native API calls are secrets.