Reputation: 25074
I'm thoroughly confused by this one. I'm running a full package worth of unit tests. Here's the relevant shared code which gets used by a number of JUnit tests:
private static Map<String, JAXBContext> jaxbContexts =
new HashMap<String, JAXBContext>();
private synchronized JAXBContext getJAXBContext(Class clazz) throws JAXBException {
JAXBContext context = null;
if (jaxbContexts.containsKey(clazz.getName())) {
context = jaxbContexts.get(clazz.getName());
} else {
context = JAXBContext.newInstance(clazz);
System.out.println("Created new context for '" + clazz.getName() + "'");
jaxbContexts.put(clazz.getName(), context);
}
return context;
}
The console output from the JUnit run includes the following two consecutive entries:
Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface'
Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface'
What am I missing? Why did jaxbContexts.containsKey()
not work in this instance for a String based key, unlike 46 other times during the JUnit execution? We aren't running our tests in parallel, but we do use Aspects if that makes a difference.
Upvotes: 2
Views: 3768
Reputation: 32014
The map can be Map<Class, JAXBContext>
instead of Map<String, JAXBContext>
for easier usage.
Upvotes: -1
Reputation: 46482
There's surely nothing special about Map containing strings as keys. Just replace the println by new Exception().printStackTrace()
and you'll see what's going on. You may be creating two instances of the class holding the map, or whatever.
Upvotes: 1
Reputation: 7376
Except for a race... But you say that you don't run things in parallel...
Anyway, I would have called context = jaxbContexts.get(clazz.getName())
and tested context
against null
.
Ah, and used the class itself as a key, because more than one class may have the same name (think class loaders)
Upvotes: 0
Reputation: 27322
Debug it and verify that the class that contains this getJAXBContext() method is instantiated only once (by checking it's has the same memory id in debug mode for every call to it). If it's different instantiations, the synchronized keyword will lock on different locks and they will use different maps.
Upvotes: 3
Reputation: 182822
Personally, I wouldn't bother with containsKey.
String name = clazz.getName();
context = jaxbContexts.get(name);
if (context == null) {
context = JAXBContext.newInstance(clazz);
System.out.println("Created new context for '" + name + "'");
jaxbContexts.put(name, context);
}
Upvotes: 1