2015-09-26 5 views
1

Я аннотированный класс Thread следующим образом:Spring JPA темы: IllegalArgumentException Исключение

@Transactional(propagation = Propagation.REQUIRED) 
@Component 
@Scope("prototype") 
public class ThreadRetrieveStockInfoEuronext implements Runnable { 
    ... 
} 

нить подключается в класс контроллера и вызывается через Global.poolMultiple.execute (threadRetrieveStockInfoEuronext);

public class RetrievelController { 

    @Autowired 
    private ThreadRetrieveStockInfoEuronext threadRetrieveStockInfoEuronext; 

    @RequestMapping(value = "/.retrieveStockInfo.htm", method = RequestMethod.POST) 
    public ModelAndView submitRetrieveStockInfo(@ModelAttribute("retrieveStockInfoCommand") RetrieveStockInfoCommand command, BindingResult result, HttpServletRequest request) throws Exception { 

     Global.poolMultiple.execute(threadRetrieveStockInfoEuronext); 
     return new ModelAndView(".retrieveStockInfo", "retrieveStockInfoCommand", command); 
    } 

Глобальный класс:

@SuppressWarnings("unchecked") 
@Component 
public class Global { 

    // create ExecutorService to manage threads 
    public static ExecutorService poolMultiple = Executors.newFixedThreadPool(10); 
    public static ExecutorService poolSingle = Executors.newFixedThreadPool(1); 
... 
} 

При запуске приложения происходит следующее исключение:

java.lang.IllegalArgumentException: Невозможно установить com.chartinvest.admin. thread.ThreadRetrieveStockInfoEuronext field

com.chartinvest.controller.RetrievelContr oller.threadRetrieveStockInfoEuronext к com.sun.proxy. $ Proxy52

ответ

3

Это потому, что ваш Runnable реализация является рессоры, аннотированный с @Transactional, и что описательные транзакции будут достигнуты, весной, обертывание фактического экземпляра класса класса внутри прокси-сервера на основе интерфейса JDK, который обрабатывает транзакцию. Вследствие этого фактический объект, который является autwired, не является экземпляром ThreadRetrieveStockInfoEuronext, а экземпляром его интерфейса Runnable, который делегирует экземпляр ThreadRetrieveStockInfoEuronext.

Обычное исправление этой проблемы заключается в том, чтобы автоувеличивать интерфейс, а не автоувеличивать конкретный тип. Но в этом случае этот класс не должен быть компонентом Spring в первую очередь, и он также не должен быть транзакционным. BTW, сделав его прототипом, дает иллюзию, что новый экземпляр будет создан при каждом вызове submitRetrieveStockInfo(), но это неверно: один экземпляр создается и автоматически добавляется в одноэлементный элемент RetrievelController, и таким же образом выполняется для всех запросы к контроллеру.

Просто сделайте ThreadRetrieveStockInfoEuronext простой класс, экземпляр его, используя новый, передавая Spring компонент в качестве аргумента, и сделать его метод run() называют транзакционный метод этого Spring бина:

@Transactional 
@Component 
public class ThreadRetrieveStockInfoEuronextImpl implements ThreadRetrieveStockInfoEuronext { 
    @Override 
    void doSomething() { ... } 
} 

public class RetrievelController { 

    @Autowired 
    private ThreadRetrieveStockInfoEuronext threadRetrieveStockInfoEuronext; 

    @RequestMapping(value = "/.retrieveStockInfo.htm", method = RequestMethod.POST) 
    public ModelAndView submitRetrieveStockInfo(@ModelAttribute("retrieveStockInfoCommand") RetrieveStockInfoCommand command, BindingResult result, HttpServletRequest request) throws Exception { 

     Runnable runnable = new Runnable() { 
      @Override 
      public void run() { 
       threadRetrieveStockInfoEuronext.doSomething(); 
      } 
     }; 

     Global.poolMultiple.execute(runnable); 
     return new ModelAndView(".retrieveStockInfo", "retrieveStockInfoCommand", command); 
    } 
+0

Большое спасибо JB для вашего посоветуйте, Решение работает отлично! – user2023141