From 19107649d23f370b30ef7e3d99528fe814addb94 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 30 Oct 2019 14:31:34 +0100 Subject: [PATCH] Revise concurrent JAXBContext creation towards computeIfAbsent Closes gh-23879 --- .../http/codec/xml/Jaxb2XmlDecoder.java | 2 +- .../http/codec/xml/Jaxb2XmlEncoder.java | 2 +- .../http/codec/xml/JaxbContextContainer.java | 27 ++++++++++--------- .../AbstractJaxb2HttpMessageConverter.java | 15 ++++------- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlDecoder.java b/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlDecoder.java index 36d2319f03..4e341a9d0e 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlDecoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlDecoder.java @@ -221,7 +221,7 @@ public class Jaxb2XmlDecoder extends AbstractDecoder { } } - private Unmarshaller initUnmarshaller(Class outputClass) throws JAXBException { + private Unmarshaller initUnmarshaller(Class outputClass) throws CodecException, JAXBException { Unmarshaller unmarshaller = this.jaxbContexts.createUnmarshaller(outputClass); return this.unmarshallerProcessor.apply(unmarshaller); } diff --git a/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlEncoder.java b/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlEncoder.java index c48869e6b9..150ad691f2 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlEncoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/xml/Jaxb2XmlEncoder.java @@ -140,7 +140,7 @@ public class Jaxb2XmlEncoder extends AbstractSingleValueEncoder { } } - private Marshaller initMarshaller(Class clazz) throws JAXBException { + private Marshaller initMarshaller(Class clazz) throws CodecException, JAXBException { Marshaller marshaller = this.jaxbContexts.createMarshaller(clazz); marshaller.setProperty(Marshaller.JAXB_ENCODING, StandardCharsets.UTF_8.name()); marshaller = this.marshallerProcessor.apply(marshaller); diff --git a/spring-web/src/main/java/org/springframework/http/codec/xml/JaxbContextContainer.java b/spring-web/src/main/java/org/springframework/http/codec/xml/JaxbContextContainer.java index 2c205c1dde..49441c498c 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/xml/JaxbContextContainer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/xml/JaxbContextContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,12 +24,13 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; -import org.springframework.util.Assert; +import org.springframework.core.codec.CodecException; /** * Holder for {@link JAXBContext} instances. * * @author Arjen Poutsma + * @author Juergen Hoeller * @since 5.0 */ final class JaxbContextContainer { @@ -37,24 +38,26 @@ final class JaxbContextContainer { private final ConcurrentMap, JAXBContext> jaxbContexts = new ConcurrentHashMap<>(64); - public Marshaller createMarshaller(Class clazz) throws JAXBException { + public Marshaller createMarshaller(Class clazz) throws CodecException, JAXBException { JAXBContext jaxbContext = getJaxbContext(clazz); return jaxbContext.createMarshaller(); } - public Unmarshaller createUnmarshaller(Class clazz) throws JAXBException { + public Unmarshaller createUnmarshaller(Class clazz) throws CodecException, JAXBException { JAXBContext jaxbContext = getJaxbContext(clazz); return jaxbContext.createUnmarshaller(); } - private JAXBContext getJaxbContext(Class clazz) throws JAXBException { - Assert.notNull(clazz, "Class must not be null"); - JAXBContext jaxbContext = this.jaxbContexts.get(clazz); - if (jaxbContext == null) { - jaxbContext = JAXBContext.newInstance(clazz); - this.jaxbContexts.putIfAbsent(clazz, jaxbContext); - } - return jaxbContext; + private JAXBContext getJaxbContext(Class clazz) throws CodecException { + return this.jaxbContexts.computeIfAbsent(clazz, key -> { + try { + return JAXBContext.newInstance(clazz); + } + catch (JAXBException ex) { + throw new CodecException( + "Could not create JAXBContext for class [" + clazz + "]: " + ex.getMessage(), ex); + } + }); } } diff --git a/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractJaxb2HttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractJaxb2HttpMessageConverter.java index 913839b001..811536c316 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractJaxb2HttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractJaxb2HttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,6 @@ import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.springframework.http.converter.HttpMessageConversionException; -import org.springframework.util.Assert; /** * Abstract base class for {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverters} @@ -106,19 +105,15 @@ public abstract class AbstractJaxb2HttpMessageConverter extends AbstractXmlHt * @throws HttpMessageConversionException in case of JAXB errors */ protected final JAXBContext getJaxbContext(Class clazz) { - Assert.notNull(clazz, "Class must not be null"); - JAXBContext jaxbContext = this.jaxbContexts.get(clazz); - if (jaxbContext == null) { + return this.jaxbContexts.computeIfAbsent(clazz, key -> { try { - jaxbContext = JAXBContext.newInstance(clazz); - this.jaxbContexts.putIfAbsent(clazz, jaxbContext); + return JAXBContext.newInstance(clazz); } catch (JAXBException ex) { throw new HttpMessageConversionException( - "Could not instantiate JAXBContext for class [" + clazz + "]: " + ex.getMessage(), ex); + "Could not create JAXBContext for class [" + clazz + "]: " + ex.getMessage(), ex); } - } - return jaxbContext; + }); } }