Czy wiesz jak poprawnie tworzyć kontekst JAXB i instancję Marshallera/Unmarshallera?

W naszych projektach często używamy JAXB w celu mapowania danych przesyłanych kopertach SOAP-owych na obiekty javowe. Aby wykonać takie mapowanie należy:
Utworzyć kontekst JAXB
JAXBContext jaxbContext = JAXBContext.newInstance(User.class);
Utworzyć marshaller/unmarshaller (w zależności do tego czy mapujemy obiekt javy na xml, czy w drugą stronę):
Marshaller marshaller = jaxbContext.createMarshaller();
// lub
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Wykonać mapowanie:
Writer writer = new StringWriter();
marshaller.marshal(user, writer);
// lub
JAXBElement<User> userElement = unmarshaller.unmarshal(source(xml), User.class);
Ważne!
Tworzenie kontekstu JAXB jest operacją czasochłonną, a doświadczenie pokazuje, że czas wywołania znacznie wzrasta wraz z liczbą wątków, które próbują wykonać współbieżnie tę operację. Dlatego zgodnie z dokumentacją, nie należy tworzyć nowej instancji kontekstu przy każdym wywołaniu mapowania. Kontekst JAXB jest bezpieczny przy współbieżnym wywołaniu. Należy go tworzyć np. w konstruktorze, metodzie inicjalizującej, jako statyczne pole klasy: To avoid the overhead involved in creating a JAXBContext instance, a JAXB application is encouraged to reuse a JAXBContext instance. An implementation of abstract class JAXBContext is required to be thread-safe, thus, multiple threads in an application can share the same JAXBContext instance.
Bardzo ważne!
W przeciwieństwie do kontekstu JAXB sam marshaller/unmarshaller nie jest bezpieczny przy współbieżnym wywołaniu! Operację tworzenia marshallera i unmarshallera trzeba powtarzać przy każdym wywołaniu. Posługiwanie się tym samym obiektem może prowadzić do nieprzewidzianych rezultatów przy większej niż jeden liczbie wątków. Co więcej, nie wyłapiemy tego błędu w testach jednostkowych i testach funkcjonalnych.
Jeżeli podczas testów wydajnościowych okaże się, że operacje tworzenia marshallera/unmarshallera zabierają zbyt dużo czasu można rozważyć utworzenie puli takich obiektów. Musi być ona zaimplementowana w taki sposób, aby różne wątki nie używały tego samego obiektu w tym samym czasie.