Nano Hash - криптовалюты, майнинг, программирование

Транзакции Spring не работают + JAX WS + JDBC

Я немного раздражен этой проблемой. Давайте проверим, реализовал ли кто-то что-то подобное.

У меня есть веб-приложение java 8 с 8 реализованными WS. Некоторые из этих WS делают вставки и обновления через JDBCTemplate (Hibernate не является выбором из-за требований к производительности), и мне нужно, чтобы они откатились, если выполнение завершается сбоем с исключением.

У меня есть следующая конфигурация источника данных и диспетчера транзакций в файле контекста приложения spring (ресурс jndi в server.xml/context.xml Tomcat):

  <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jdbc/source" />
  </bean>
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
  </bean>

  <tx:annotation-driven transaction-manager="transactionManager" />

С другой стороны, у меня есть уникальная точка доступа к базе данных DBcontroller.class, которая имеет общий метод для вставки, удаления и обновления:

private NamedParameterJdbcTemplate jdbcTemplate;
private DataSource datasource;

@Autowired
public void setDataSource(DataSource dataSource) {
    this.datasource = dataSource;
    this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
@Override
public boolean queryForModifying(String query, SqlParameterSource parameters) {

  int modifiedRows= 0;
  try {
      modifiedRows= this.jdbcTemplate.update(query, parameters);
  } catch (Exception e) {
      e.printStackTrace();
      numRegistrosAfectados = 0;
  }
  return (modifiedRows> 0) ? true : false;
}

Наконец, у меня есть интерфейс WS. Таким образом:

@WebService
public interface IService{

    @WebMethod
    public method(MethodRequestType request) throws IllegalArgumentException, IllegalAccessException;

}

с его реализацией:

@WebService(endpointInterface = "com.package.IService")
@HandlerChain(file = "handler-chain.xml")
public class Service implements IService{

    @Autowired
    IDBController dbController;

с "транзакционным" методом:

@Transactional
private boolean inserts(HashMap<String, Object> input, MethodRequestType request) {.....

Он должен работать нормально в проекте, отличном от WS, но, как я обнаружил, нет такого простого способа сделать эту работу.

Сначала я думал, что это не откат, но теперь я совершенно уверен, что он не создает транзакции.

В stackoverflow есть похожие сообщения, но ни один из них не решает мою проблему. Я много гуглил, и единственный предложенный способ - это WS-AtomicTransactions, о котором я никогда не слышал.

Я пробовал почти все в файле конфигурации XML, я даже пытался программно управлять транзакциями, но, поскольку это пул соединений, я не могу установить для автофиксации значение false, чтобы я мог принудительно откатываться.

Ибо если кому пригодится, у меня для каждой WS реализованы обработчики мыла, которые выглядят так:

public class ServiceHandler implements SOAPHandler<SOAPMessageContext> {

    private SoapFaultHandler soapFaultHandler;

    @Override
    public boolean handleMessage(SOAPMessageContext context) {

        SOAPMessage message = context.getMessage();
        soapFaultHandler = new SoapFaultHandler(message);
        return SoapMessageHandler.handleMessage(context, "Service name", logger);
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return soapFaultHandler.handleFault(context, logger, "ServiceName");

    }
    ...
}

Ответы:


1

Имеет значение, где вы вызываете метод, аннотированный @Transactional. Например, если у вас есть:

@Service
public class Service1 {

    @Transactional
    public void method1() { ... }

    public void method2() {
        method1();
    }
}

@Service
public class Service2 {

    @Autowired
    private Service1 service1;

    public void method1() {
        service1.method1();
    }

    public void method2() {
        service1.method2();
    }
}
  • Вызов service2.method2() НЕ создаст транзакцию.
  • Вызов service2.method1() создаст его.

Из-за того, как Spring обрабатывает прокси и АОП.

06.08.2018

2

прочитав документацию по Spring вы можете прочитать следующее (жирным жирным шрифтом важные предложения)

  • Недостаточно сказать вам, чтобы вы просто аннотировали свои классы аннотацией @Transactional, добавили @EnableTransactionManagement в свою конфигурацию, а затем ожидали, что вы поймете, как все это работает. В этом разделе объясняется внутренняя работа инфраструктуры декларативных транзакций Spring Framework в случае проблем, связанных с транзакциями.

  • Наиболее важные концепции, которые следует усвоить в отношении поддержки декларативных транзакций Sspring Framework, заключаются в том, что эта поддержка осуществляется через прокси-серверы AOP, и что рекомендации по транзакциям управляются метаданными (в настоящее время основанными на XML или аннотациях). ). Сочетание АОП с транзакционными метаданными дает прокси-сервер АОП, который использует TransactionInterceptor в сочетании с соответствующей реализацией PlatformTransactionManager для управления транзакциями вокруг вызовов методов.

  • При использовании прокси аннотацию @Transactional следует применять только к общедоступным методам. Если вы аннотируете защищенные, частные или видимые для пакета методы с помощью аннотации @Transactional, ошибка не возникает, но аннотированный метод не отображает настроенные параметры транзакций. Рассмотрите возможность использования AspectJ (см. ниже), если вам нужно аннотировать непубличные методы.

Поэтому, пожалуйста, попробуйте изменить модификатор вашего метода «вставки» с частного на общедоступный.

06.08.2018
  • Я уже пробовал это, на самом деле это правильная версия с общедоступным методом, но когда я опубликовал это, оно было изменено из-за тысяч попыток, которые я сделал. Спасибо, в любом случае 06.08.2018

  • 3

    Наконец-то я нашел способ! Я был очень близок всегда:

    • Транзакционный метод (как сказал Гави) должен быть общедоступным (но это не проблема, потому что я пробовал его раньше).

    • Транзакционный метод должен находиться в другом классе, а не в аннотированном классе Webservice.

    • Этот класс должен быть автоматически связан, чтобы он находился в контексте Spring.

    • В этом классе я автоматически подключил экземпляр DbController.

    И это было все.

    Моя главная проблема заключалась в том, что я издевался над этим классом и создавал его с помощью «нового», вместо этого позволяя Spring творить свое волшебство.

    Спасибо за ответы, надеюсь помочь другим!

    09.08.2018
  • вы сказали: транзакционный метод должен быть в другом классе, а не в аннотированном классе Webservice. Но с общедоступной стратегией: сделать слой контроллера владельцем транзакции и работать с предположением, что метод общедоступного контроллера не должен вызывать другой в любом сценарии. У нас амбивалентность с вашими словами, Итак, Мой Вопрос. как мы можем управлять транзакциями в приложении с уровнем WS? Подсказка: уровень контроллера и уровень веб-сервиса всегда являются одними и теми же слоями. 24.09.2018
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..