DatatypeFactory is poorly designed both in terms of usability and performance.
From the usability point of view, it's suffice to show the following code that average developers have to write to get one XMLGregorianCalendar instance created:
XMLGregorianCalendar cal;
try {
cal = DatatypeFactory.newInstance().newXMLGregorianCalendar(...);
} catch(DatatypeConfigurationException e) {
// huh?
assert false;
}
This is ridiculously long compared to other common value object creation, such as "new URL(String)" or even to "new Date()".
Another problem is that DatatypeFactory.newInstance() throws a checked DatatypeConfigurationException, which forces users to handle it, even though this is simply a deployment error and nothing a running application can meaningfully handle. It's worth pointing out that neither SAXParserFactory.newInstance() nor DocumentBuilderFactory.newInstance() throws any checked exception (correctly!)
The other usability issue is the lack of convenience methods to create XMLGregorianCalendar in various formats. For example, there's no easy way to create an XMLGregorianCalendar instance that represents today in xs:gDate. Even creating xs:dateTime representation of Today requires the user to create a new GregorianCalendar instance, then to XMLGregorianCalendar.
The performance aspect of this is equally bad, as DatatypeFactory.newInstance() goes through the complete service look up mechanism. See the comment section for the performance numbers.
On a relevant performance note, the spec should require that DatatypeFactory be thread safe. Since DatatypeFactory is stateless today, this shouldn't be a problem (The JAXP RI implements this in a thread-safe way.) If there's any implementation that cannot make this thread-safe, they only need to put synchronized keyword on their methods.
All in all, I suggest the following change to DatatypeFactory.
- Require that DatatypeFactory be reentrant by multiple threads.
- Deprecate DatatypeFactory, citing performance and usability reasons.
- Move newXXX methods from DatatypeFactory to Duration and XMLGregorianCalendar and make them static.
With is, the user would now say something like this:
XMLGregorianCalendar.createToday();
XMLGregorianCalendar class should maintain one static final DatatypeFactory instance to delegate
all static createXXX method invocations to. The same for Duration.
- When you move factory methods, this is also a good opporunity to think hard about the kind of
methods you want to define. For example, creating uninitialized XMLGregorianCalendar is far less
common than creating the XMLGregorianCalendar that represents "now". So the no-arg factory method
should be probably used for creating "now" as opposed to creating uninitialized one.
These changes together make XMLGregorianCalendar and Duration more usable and performant, without adding any more work to the developers.
From the usability point of view, it's suffice to show the following code that average developers have to write to get one XMLGregorianCalendar instance created:
XMLGregorianCalendar cal;
try {
cal = DatatypeFactory.newInstance().newXMLGregorianCalendar(...);
} catch(DatatypeConfigurationException e) {
// huh?
assert false;
}
This is ridiculously long compared to other common value object creation, such as "new URL(String)" or even to "new Date()".
Another problem is that DatatypeFactory.newInstance() throws a checked DatatypeConfigurationException, which forces users to handle it, even though this is simply a deployment error and nothing a running application can meaningfully handle. It's worth pointing out that neither SAXParserFactory.newInstance() nor DocumentBuilderFactory.newInstance() throws any checked exception (correctly!)
The other usability issue is the lack of convenience methods to create XMLGregorianCalendar in various formats. For example, there's no easy way to create an XMLGregorianCalendar instance that represents today in xs:gDate. Even creating xs:dateTime representation of Today requires the user to create a new GregorianCalendar instance, then to XMLGregorianCalendar.
The performance aspect of this is equally bad, as DatatypeFactory.newInstance() goes through the complete service look up mechanism. See the comment section for the performance numbers.
On a relevant performance note, the spec should require that DatatypeFactory be thread safe. Since DatatypeFactory is stateless today, this shouldn't be a problem (The JAXP RI implements this in a thread-safe way.) If there's any implementation that cannot make this thread-safe, they only need to put synchronized keyword on their methods.
All in all, I suggest the following change to DatatypeFactory.
- Require that DatatypeFactory be reentrant by multiple threads.
- Deprecate DatatypeFactory, citing performance and usability reasons.
- Move newXXX methods from DatatypeFactory to Duration and XMLGregorianCalendar and make them static.
With is, the user would now say something like this:
XMLGregorianCalendar.createToday();
XMLGregorianCalendar class should maintain one static final DatatypeFactory instance to delegate
all static createXXX method invocations to. The same for Duration.
- When you move factory methods, this is also a good opporunity to think hard about the kind of
methods you want to define. For example, creating uninitialized XMLGregorianCalendar is far less
common than creating the XMLGregorianCalendar that represents "now". So the no-arg factory method
should be probably used for creating "now" as opposed to creating uninitialized one.
These changes together make XMLGregorianCalendar and Duration more usable and performant, without adding any more work to the developers.
- relates to
-
JDK-6201270 Factory method to create an XMLGregorianCalendar instance filled with the current time
-
- Closed
-