Как обновить значение строки с помощью репозитория JPA вне контроллера? - PullRequest
1 голос
/ 13 мая 2019

Я пытался обновить данные строки таблицы из-за пределов контроллера (внутри некоторых потоков) и всегда получать исключение NullPointerException.

Код темы:

public class S3Thread implements Runnable {

@Autowired  
private IAutomationService automationService;

@Override
public void run() { 
    Automation config = new Automation("user1","success");
    automationService.updateAutomation(config);
 }
}

Исключение NullPointer, выданное в нижней строке: automationService.updateAutomation (конфигурации); * * 1 006

Примечание. Мне удалось создать / обновить класс контроллера. Только в теме.

Ответы [ 4 ]

1 голос
/ 14 мая 2019

Ну, это классический Почему у меня поле Spring @Autowired null. Вы создаете экземпляр S3Thread самостоятельно, и поэтому в него не вводятся бобы.

Учитывая, что вы пытаетесь сделать что-то в отдельном потоке, вы можете использовать @Async:

@Async
public void updateAutomationConfiguration() {
    Automation config = new Automation("user1", "success");
    automationService.updateAutomation(config);
}

Примечания :

  • Вы должны добавить аннотацию @EnableAsync к любому классу конфигурации (например, вашему основному классу), чтобы эта работа работала.
  • Spring по умолчанию использует прокси, что означает, что вы не можете добавить этот класс updateAutomationConfiguration() в свой контроллер. Прямые вызовы методов в пределах одного и того же компонента обходят прокси-логику. Решение состоит в том, чтобы поместить этот метод в отдельный bean-компонент, который может быть подключен автоматически и вызываться из контроллера. Я дал более подробные ответы об альтернативных решениях в этом ответе .

В Spring также есть руководство по началу работы с созданием асинхронных методов .


В качестве альтернативы, есть также несколько способов выполнения асинхронных вызовов внутри контроллеров , например, с помощью CompletableFuture внутри контроллера:

@PutMapping("/automation/configuration")
public CompletableFuture<String> updateAutomationConfiguration() {
    return CompletableFuture.supplyAsync(() -> {
        Automation config = new Automation("user1", "success");
        return automationService.updateAutomation(config);
    });
}

Related: Как создать неблокирующую @RestController веб-службу в Spring?

0 голосов
/ 13 мая 2019

Есть 2 возможных решения вашей проблемы:

Либо вам нужно сделать S3Thread класс службой, пометив его с помощью @Service или @Component и автоматически связав его с вызывающим классом, либо вы можете использовать конструктор для инициализации automationService, например, private IAutomationService automationService = new AutomationService();

0 голосов
/ 13 мая 2019

Так как ваш класс потока не управляется Spring, вы не сможете внедрить bean-компоненты, управляемые пружиной, в класс S3Thread.

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

Как только вы овладеете этим классом, вы можете получить соответствующий bean-компонент и передать ссылку на / или использовать непосредственно в классе S3Thread. Как то так

@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext appContext)
    {
        ctx = appContext;

    }

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }
}
public class S3Thread implements Runnable {


@Override
public void run() { 
    Automation config = new Automation("user1","success");
 IAutomationService automationService= 
      ApplicationContextUtils.getApplicationContext().getBean(IAutomationService .class);
    automationService.updateAutomation(config);
 }
}
0 голосов
/ 13 мая 2019

Spring не сканирует ваш исполняемый файл, так как он не помечен @ Component. Попробуйте пометить его @ Component / @ Service. Не забудьте установить требуемую область действия!

...