Служба Spring NullPointerException Веб-служба Джакарты

@Path("/abc")
@Produces(MediaType.APPLICATION_JSON)
public class ABCController
{
   @Autowired
   private MyService myService;

   @GET
   public Response getSome(@QueryParam("identification") List<String> ids)
   {
      GenericEntity<List<Label>> entity = new GenericEntity<>(myService.findSomething(ids))
      {
      };
      return Response.ok(entity).build();
   }

МойСервис:

@RequiredArgsConstructor
@Service
public class MyService
{
   private final MyMapper myMapper;

   private final JpaRepository myRepository;

   public List<String> findSomething(ids){
         myRepository.findXYZ(ids);
   }

Мой основной класс:

@SpringBootApplication
public class MainClass
{
   public static void main(String[] args)
   {
      SpringApplication.run(MainClass.class, args);
   }

   @Bean
   public MyMapper myMapper()
   {
      return new MyMapperImpl();
   }
}

построить.градле:

buildscript {
    ext {
        LOMBOK_VERSION = "1.18.22"
        SPRING_BOOT_VERSION = "2.6.6"
        JERSEY_VERSION = "3.0.8"
        JACKSON_VERSION = "2.13.1"
        MSSQL_JDBC_VERSION = "9.4.1.jre11"
        MAPSTRUCT = "1.5.1.Final"
    }
}

plugins {
    id "org.gretty" version "4.0.3"
}

apply plugin: 'java-library'
apply plugin: 'java'
apply plugin: 'war'

repositories {
    mavenLocal()
    maven {
        url = '...'
    }
}


dependencies {
    compileOnly "org.projectlombok:lombok:${LOMBOK_VERSION}"
    testImplementation "org.projectlombok:lombok:${LOMBOK_VERSION}"
    annotationProcessor "org.projectlombok:lombok:${LOMBOK_VERSION}"

    implementation "org.mapstruct:mapstruct:${MAPSTRUCT}"
    annotationProcessor "org.mapstruct:mapstruct-processor:${MAPSTRUCT}"

    implementation "org.springframework.boot:spring-boot-starter-data-jpa:${SPRING_BOOT_VERSION}"

    implementation "com.microsoft.sqlserver:mssql-jdbc:${MSSQL_JDBC_VERSION}"

    implementation "org.glassfish.jersey.containers:jersey-container-servlet-core:${JERSEY_VERSION}"
    implementation "org.glassfish.jersey.inject:jersey-hk2:${JERSEY_VERSION}"
    implementation "org.glassfish.jersey.media:jersey-media-json-jackson:${JERSEY_VERSION}"
}

Когда я звоню http://localhost:8080/myservice/abc?identification=61234561234569,71234561234568,71234561234569

я получил NullPointerException из myService.findSomething(ids)

Я запускаю приложение с помощью команды gradle appRun

вы фактически не создаете экземпляры полей MyService. Итак: myRepository.findXYZ(ids); на самом деле: null.findXYZ(ids);

Stultuske 30.09.2022 11:49

Отвечает ли это на ваш вопрос? Что такое исключение NullPointerException и как его исправить?

Stultuske 30.09.2022 11:49

Проблема: для «автоматической проводки» запрашивающий объект должен быть «пружинным управлением» ... ваш ABCController, похоже, не такой!

xerx593 30.09.2022 11:58

Так что аннотация @Component на ABCController исправит это...

xerx593 30.09.2022 12:00

... у вас есть альтернативные варианты (@Bean в классе конфигурации (развязка...!), или @Service, @Repository аннотации, ... и я пытаюсь выяснить, что было бы лучшим/общим для "Jakarta ws". .

xerx593 30.09.2022 12:03

Для авто-проводки: оба объекта (проводные и проводные) должны быть "пружинными (бинами)"! ;) В MyService это достигается с помощью аннотации @Service.

xerx593 30.09.2022 12:06

@Stultuske не имеет значения, и я это знаю. Вопрос в том, почему я должен его создавать. это сервисный объект

emoleumassi 30.09.2022 12:24

@emoleumassi вы читали комментарии xerx593? Это он уже объяснил. или вы говорили о полях в MyService? В этом случае да, MyService — это сервис, его поля — нет.

Stultuske 30.09.2022 12:25

@Stultuske JpaRepository - это JpaRepository, и у меня есть боб MyMapper в MainClass

emoleumassi 30.09.2022 12:29
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
9
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Несмотря на то, что Spring предлагает свою собственную «инфраструктуру для разработки REST-Service» (spring-web ), не должно быть никаких причин, по которым JAX-RS не мог бы использовать spring-core и даже spring-boot.


Проблема (для этого конкретного NPE):

Для авто-проводки: оба объекта (проводные и проводные) должны быть "пружинными (бинами)"! ;) В MyService это достигается с помощью аннотации @Service.

Чтобы решить эту проблему, нам также нужно подключить ABCController в контексте spring!


«Наименее навязчивый»/самый простой подход — аннотировать ABCController с помощью @Component:

...
import org.springframework.stereotype.Component;

@Component // !
@Path("/abc")
@Produces(MediaType.APPLICATION_JSON)
public class ABCController ...

Это (+ правильное «сканирование компонентов») «поднимет» ABCController в контекст весны и включит автоматическое подключение (от/к) этого объекта.


Другой подход, отделяющий «реализации» от spring:

Для этого нам нужно удалить все (возможные) org.springframework.* импорты из наших «пружинно-независимых» классов. (Конечно, это невозможно в очень специфичных классах spring (spring-web(Rest)Controllers, Spring-data-repos,...).

  • Чтобы заменить аннотации @Component/Service/Repository, мы перемещаем экземпляры в аннотированные методы @Bean в нашу конфигурацию Spring (класс (ы)) (.. см. Бин MyMapper!)
  • Чтобы заменить @Autowired, нам пришлось бы «связывать» их вручную или использовать «автоматическое связывание неявного конструктора» (в рамках упомянутых методов @Bean)

Итак, ваш Config(/SpringBootApp) может выглядеть так:

@SpringBootApplication
public class MainClass
{
   public static void main(String[] args)
   {
      SpringApplication.run(MainClass.class, args);
   }

   @Bean
   public MyMapper myMapper()
   {
      return new MyMapperImpl();
   }
   
   @Bean // singleton is default "scope"!!...
   public MyService myService(/*implicitly @Autowired :*/ JPARepository repo, MyMapper mapper /* ..and taken care (hopefully;) by spring*/) {
    return new MyService(mapper, repo);
   }
   // and:
   @Bean 
   public ABCController abcController(/*implicitly @Autowired :*/ MyService service /* ..and taken care (hopefully;) by spring*/) {
    ABCController bean = new ABCController();
    bean.setMyService(service);
    return bean; 
  }
}

С соответствующими настройками ABCController:


@Path("/abc")
@Produces(MediaType.APPLICATION_JSON)
public class ABCController
{
   // NOT @Autowired
   private MyService myService;
   ...
   // Setter(/getter) for myService !

При добавлении @RequiredArgsConstructor к ABCController подходящего конструктора найти не удалось. Ошибка: java.lang.NoSuchMethodException: Could not find a suitable constructor in ABCController class.

emoleumassi 30.09.2022 13:03

Вы пробовали "наименее навязчиво"? ..конечно @RequiredArgsConstructor более навязчиво!!:)) ..но много альтернатив ..(один из них: удалить @RequiredArgsConstructor, удалить модификатор final, ввести сеттер, ..использовать его в методе компонента..)

xerx593 30.09.2022 13:06

Итак, кажется, что jax-rs (.. или что-то в конце этой трассировки стека) нуждается в «конструкторе по умолчанию (т.е. без аргументов)» для ABCController..

xerx593 30.09.2022 13:13

Я обновил ответ, чтобы не использовать @RequiredArgsConstructor ..

xerx593 30.09.2022 13:19
Ответ принят как подходящий

Это зависимость для джерси в весенней загрузке: spring-boot-starter-jersey

build.gradle выглядит так:

buildscript {
    ext {
        LOMBOK_VERSION = "1.18.22"
        SPRING_BOOT_VERSION = "2.6.6"
        JERSEY_VERSION = "3.0.8"
        JACKSON_VERSION = "2.13.1"
        MSSQL_JDBC_VERSION = "9.4.1.jre11"
        MAPSTRUCT = "1.5.1.Final"
    }
}

apply plugin: 'java-library'
apply plugin: 'java'
apply plugin: 'war'

repositories {
    mavenLocal()
    maven {
       ...
    }
}


dependencies {
    compileOnly "org.projectlombok:lombok:${LOMBOK_VERSION}"
    testImplementation "org.projectlombok:lombok:${LOMBOK_VERSION}"
    annotationProcessor "org.projectlombok:lombok:${LOMBOK_VERSION}"

    implementation "org.mapstruct:mapstruct:${MAPSTRUCT}"
    annotationProcessor "org.mapstruct:mapstruct-processor:${MAPSTRUCT}"

    implementation "org.springframework.boot:spring-boot-starter-jersey:${SPRING_BOOT_VERSION}"
    implementation "org.springframework.boot:spring-boot-starter-data-jpa:${SPRING_BOOT_VERSION}"

    implementation "com.microsoft.sqlserver:mssql-jdbc:${MSSQL_JDBC_VERSION}"
}

Контроллер становится @Component

@Path("/abc")
@Produces(MediaType.APPLICATION_JSON)
@Component
public class ABCController
{
   @Autowired
   private MyService myService;

   @GET
   public Response getSome(@QueryParam("identification") List<String> ids)
   {
      GenericEntity<List<Label>> entity = new GenericEntity<>(myService.findSomething(ids))
      {
      };
      return Response.ok(entity).build();
   }

MainClass - это сервлет:

@SpringBootApplication
public class MainClass extends SpringBootServletInitializer
{
   public static void main(String[] args)
   {
      new MainClass().configure(new SpringApplicationBuilder(MainClass.class)).run(args);
   }

   @Bean
   public MyMapper myMapper()
   {
      return new MyMapperImpl();
   }
}

MyService — это @Service

@RequiredArgsConstructor
@Service
public class MyService
{

Я добавил JerseyConfig:

@Component
public class JerseyConfig extends ResourceConfig
{
   public JerseyConfig()
   {
      register(ABCController.class);
   }
}

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