简体   繁体   中英

@Autowired service from Spring Boot is null in WAR

first of all I apologize for the inconvenience, I make this consultation because I have spent days with this problem and I do not find the right solution. I have a project called fact-electronica-api designed using swagger codegen, through this I have the paths to perform REST calles. Once the user makes a call of this type the api project communicates with another project that has the core which use Spring Boot and performs the query with the database. The problem I have is that when I make from the api an autowired to the service defined in the core this is null.

Excuse my English, I am from Uruguay, I hope you understand the problem I am facing.For further understanding, I have attached images.

  • Fact electronica Api

在此处输入图片说明

  • Factelec-core

在此处输入图片说明

Service through which I receive the rest call and communicate with the core.

在此处输入图片说明

Service in core

在此处输入图片说明

Dependence on the api to the core

在此处输入图片说明

Spring Boot initializer, when you start the ear in wildfly, this project starts automatically and makes the relevant settings.

在此处输入图片说明

I would be grateful if someone could guide me in solving this problem, thank you in advance.

Seems like SolicitudApiServicelmpl isn't a Spring bean, so Spring wouldn't consider all class's fields annotated with @Auowired for dependency injection. Try to annotate this class as @Service to add the class's instance to Spring context or create a factory for SolicitudApiServicelmpl which generates Spring proxy instead of a simple object.

You are not creating SolicitudApiServicelmpl spring instance.

Spring context (witch makes @Autowired work) needs you to create that instance thought to Spring and not with a java native new SolicitudApiServicelmpl() .

You can create that instance with a lot of techniques, here you have some of them:

Static context with "manual wired" (not recommended)

public class Main {

   private static ConfigurableApplicationContext context;

   public static void main(String[] args) {
      context = SpringApplication.run(MyApplication.class, args);
   }

   public static ConfigurableApplicationContext getContext() {
      return context;
   }

}
public class SolicitudApiServicelmpl {

   private ConfigurableApplicationContext context = Main.getContext();

   private SolicitudInformacionService solInfServ = context.getBean(SolicitudInformacionService.class);

   // Now `solInfServ` is not null anymore.
   // ...
}

Creating a SolicitudApiServicelmpl instance within the Spring context

@Component
public class SomeClassWithSpringContext {

   @Autowired private SolicitudApiServicelmpl solicitudService;
   // with this @Autowired should work in the `service` instance.

}

or with the context instance:

@Component
public class SomeClassWithSpringContext {

   @Autowired private WebApplicationContext context;

   public void someMethodOrSomewhere() {
      SolicitudApiServicelmpl service = context.getBean(SolicitudApiServicelmpl.class);
      // with this @Autowired should work in the `service` instance.
   }

}

after the help that was given to me by Nurio Fernández and Andrei Kovrov i was able to find out the right way to accomplish what i wanted to do.

First of all I integrate Spring into the api, and not only into the core, moving spring boot from the core to the api, resulting in this class in the api.

Api - ApplicationInitializer.java

@Order(Ordered.HIGHEST_PRECEDENCE)
@SpringBootApplication(scanBasePackages = {"com.factelcore.*","uy.com.antel.fact.*"})
@EnableJpaRepositories("com.factelcore.repository")
public class ApplicationInitializer extends SpringBootServletInitializer {
    
    public static void main(String[] args){
        SpringApplication.run(ApplicationInitializer.class,args);
    }
    
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(applicationClass);
    }
 
    private static Class<ApplicationInitializer> applicationClass = ApplicationInitializer.class;
    
}

By doing this I made sure I had a spring context in the api, which I could work with. When I start Spring from here I scan all the api and core files, performing the appropriate configuration of the beans.

After doing this, I needed to capture the context to recover the beans that are defined in the core, so I could work with the @Service class defined in the core. For this I created the following class:

Api - AppContextUtil.java

@Component
public class AppContextUtil implements ApplicationContextAware {
    
    @Autowired 
    private WebApplicationContext context;

    private static ApplicationContext appContext;
    
    @PostConstruct
    public void init() {
        if (context != null) {
            setApplicationContext(context);         
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        AppContextUtil.appContext = applicationContext;
    }

    public static ApplicationContext getContext() {
        return appContext;
    }
}

Once this was done, using the SolicitudApiServiceImpl I was able to do the following to invoke the bean I needed at a certain time:

Api - SolicitudApiServiceImpl.java

ApplicationContext cont = AppContextUtil.getContext();
SolicitudInformacionService solInfServ = cont.getBean(SolicitudInformacionService.class);

I don't know if this is the ideal way to do this, but in my case it worked for me, if there is someone who has a better way to do it feel free to tell me so I can improve the code. Thank you very much!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM