Завершить операцию Java API, не останавливая приложение

Я пытаюсь остановить операцию API в java, под которой я подразумеваю остановку процесса, который выполняется как часть вызова API. Мой апи выглядит так:

@RequestMapping(value = "/startProcess",method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
            public ResponseEntity<String> startProcess(
  @Parameter(@RequestBody testBody)
        ) {
          
         String somekindofID = testservice.startProcess();
         return new ResponseEntity<>(someKindofID, HTTPStatus.OK);
        }



@RequestMapping(value = "/testPID",method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<String> TestPID(
            @Parameter(name = "somekindofID",required = true) @Valid @RequestBody String somekindofID)
    ) {
      
     //get the ID from the above api and kill the running process
    }



public String startProcess() {      
   long pid = 0;
    new Thread(()-> {
        try {
                int exitCode = startProcessBuilderwithCommand(); //starts a processbuilder with batch file
                if (exitCode != 0) {
                     return;
                }else{                        
                   pid=consumer.initiateConsumer(); -> this is the process which needs to stop
                }
            } catch (Exception e) {
                e.printStackTrace();
                return;
            }
    }).start();

    return pid;
}

Теперь я попытался использовать Java 9 ProcessHandle.current().pid() но он дает PID самого приложения Java, который, если я использую для taskkill, завершит все приложение.

Есть ли способ получить идентификатор или что-то еще только из операции API, чтобы я мог завершить ее, не завершая все приложение Java?

Другими словами, я хотел бы завершить фоновый процесс, не убивая приложение.

P.S. метод testservice.startProcess() возвращает идентификатор метода initialconsumer(), который я пытаюсь убить, не убивая приложение

Ну и где код запускающий процесс? Это не то, как работают API. Вам либо нужно, чтобы API возвращал PID, а затем вызывающий абонент может вызвать другой API, чтобы остановить его, но это звучит как проблема дизайна.

OldProgrammer 12.04.2023 18:29

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

Ananya 12.04.2023 18:31

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

andrewJames 12.04.2023 18:34

Я добавил отредактированный код, который можно воспроизвести.

Ananya 12.04.2023 18:48

поэтому, если вы возвращаете PID, если порожденный процесс, вам нужно написать другой API, чтобы вызывающая сторона могла его остановить? При этом уничтожение процесса в процессе выполнения работы может привести к непредсказуемому поведению. Поскольку мы не знаем, что делает этот процесс, кто знает, каковы будут результаты.

OldProgrammer 12.04.2023 19:00

это не процесс, который я хочу убить, а Consumer.initiateConsumer(); запускает потребителя kafka, который работает в фоновом режиме. И я намерен остановить этого потребителя

Ananya 12.04.2023 19:02
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

По сути вам нужно следующее.

  1. Потребитель, запущенный с помощью InitialConsumer(), должен содержать механизм, который он используется для проверки того, был ли он остановлен другим процессом.

  2. способ определить, какого потребителя остановить.

@контроллер

@RequestMapping(value = "/startProcess", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Integer> startProcessPost(@RequestBody String testBody) {

int somekindofID = testservice.startProcess();
return new ResponseEntity<>(somekindofID, HttpStatus.OK);
}

@RequestMapping(value = "/testPID", method = RequestMethod.GET)

public ResponseEntity<Void> TestPID(@RequestParam(name = "somekindofID", required = true) int somekindofID) {
    Consumer.killConsumer(somekindofID);
    return new ResponseEntity<>(HttpStatus.OK);

}

Потребитель

public class Consumer {

    private static Map<Integer, Consumer> runningConsumers = new HashMap<>();
    
    boolean running;
    
    public int initiateConsumer() {
        running = true;
        int hashCode = hashCode();
        runningConsumers.put(hashCode, this);
        // pass the work into a Runnable
        return hashCode;
    }
    
    public static void killConsumer(int hashCode) {
        Consumer consumerToBeKilled = runningConsumers.get(hashCode);
        consumerToBeKilled.running = false;
        
    }
    
    private void consumerActivity() {
        while(running) {
            // keep working
        }
        // take me out of the Map
        int hashCode = hashCode();
        runningConsumers.remove(hashCode);

    }

}

ТестСервис

public class TestService {

    final Consumer consumer = new Consumer();

    public int startProcess() {
        final int[] pidHolder = new int[] {-1}; // because only finals can be passed to threads
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                try {
                    int exitCode = startProcessBuilderwithCommand(); // starts a processbuilder with batch file
                    if (exitCode != 0) {
                        return;
                    } else {
                        pidHolder[0] = consumer.initiateConsumer(); // -> this is the process which needs to stop
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    return;
                }
            }
        };

        return pidHolder[0];
        
    }

Обратите внимание, что остановить поток извне еще сложнее — java-thread-stop — также нужно что-то смотреть изнутри.

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