JAXB.marshal блокирует вызов веб-сервиса

Я использую Spring WebserviceTemplate, чтобы сделать SOAP-вызов службы. Я запустил тест производительности, чтобы увидеть, как он ведет себя под нагрузкой. У меня также есть перехватчик для копирования параметров заголовка из моего входящего запроса в службу, которую я вызываю.

@Component
public class HeaderPropagationInterceptor implements ClientInterceptor {

    @Override
    public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
        SoapMessage request = (SoapMessage) messageContext.getRequest();
        Result result = request.getSoapHeader().getResult();
        JAXB.marshal(getRequestHeader(), result);
        return true;
    }

Когда я запускаю тест производительности, я вижу нижеприведенную блокировку оператора на 4-5 секунд

JAXB.marshal(getRequestHeader(), result);

Есть ли причина, по которой это может блокировать?

1 ответ

Решение

Служебный класс JAXB создаст JAXBContext при первом его вызове (дорогая операция). Он будет слабо кэширован, что означает, что при нехватке памяти контекст может быть переработан и воссоздан при следующем вызове. Вы действительно должны создать свой контекст и сохранить его в явном виде. Примерно так (как уже предлагалось в комментариях других) должно решить вашу проблему:

@Component
public class HeaderPropagationInterceptor implements ClientInterceptor
{
    private JAXBContext jaxbContext;

    @PostConstruct
    public void createJaxbContext() {
        try {
            jaxbContext = JAXBContext.newInstance(RequestHeader.class);
        }
        catch(JAXBException e) {
            throw new IllegalStateException("Unable to create JAXBContext.", e);
        }
    }

    @Override
    public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
        SoapMessage request = (SoapMessage) messageContext.getRequest();
        Result result = request.getSoapHeader().getResult();
        jaxbContext.createMarshaller().marshal(getRequestHeader(), result);
        return true;
    }
}

Вы должны заменить RequestHeader.class с фактическим классом, используемым вашим кодом. Если требуется дальнейшее улучшение производительности, можно также использовать локальный поток для повторного использования маршаллера, но вам, вероятно, следует выполнить дополнительное профилирование, чтобы убедиться, что это действительно узкое место. Удачи с вашим проектом!

Другие вопросы по тегам