Nullpointer when using #Autowire - java

I want to create a DAO object by dependency injection (#Autowire) but unfortunately, this DAO object is never created and hence a Nullpointer exception is thrown.
This is my DAO implementation:
package com.sample.dao.service;
#Component
public class OrderServiceImpl implements OrderService {
private final OrderRepository orderRepository;
#Autowired
OrderServiceImpl(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
#Override
public void save(Order order) {
return orderRepository.save(order);
}
The class where the Nullpointer exception is caused:
package com.sample.dispatcher;
#Component
public class OrderDispatcher {
private final OrderServiceImpl orderServiceImpl;
#Autowired
public OrderDispatcher(OrderServiceImpl orderServiceImpl) {
this.orderServiceImpl = orderServiceImpl;
}
public void createOrder(Order order) {
orderServiceImpl.save(order)); // --> Nullpointer
My entry class:
package com.sample;
#SpringBootApplication
#ComponentScan(basePackages = { "com.sample" , "com.webservice"})
#EnableJpaRepositories(basePackages = "com.sample.dao.repository")
public class Application {
public static void main(final String[] args) {
SpringApplication.run(Application.class, args);

I think you should change your constructor to have an argument type of interface rather than a concrete implementation. So something like this -
#Component
public class OrderDispatcher {
private final OrderService orderServiceImpl;
#Autowired
public OrderDispatcher(OrderService orderServiceImpl) {
this.orderServiceImpl = orderServiceImpl;
}
When you add the #component notation on OrderServiceImpl, Spring creates proxy for that class and it can be autowired by interface.

Maybe you forgot the #annotation configuration. Try adding this class and also you scan your entities: EntityScan
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#Configuration
#EntityScan("com.sample.model") // Your model package
#ComponentScan(basePackages = { "com.sample" , "com.webservice"})
#EnableJpaRepositories(basePackages = "com.sample.dao.repository")
public class RepositoryConfig {
}

Related

Parameter 0 of constructor in my class required a bean of my second class that could not be found

I know it's a problem that is been posted 100 times, but unfortunately I am getting a Defining Bean error in my Spring Boot Application and I really do not know why. I do not see my error from launch to finish since I am defining a bean.
I would appreciate any help.
I'm sure it's a stupid mistake which I just don't see
My error Code
Description:
Parameter 0 of constructor in com.example.demo.jwt.JwtSecretKey required a bean of type 'com.example.demo.jwt.JwtConfig' that could not be found.
Action:
Consider defining a bean of type 'com.example.demo.jwt.JwtConfig' in your configuration.
JwtSecretKey class
package com.example.demo.jwt;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.crypto.SecretKey;
#Configuration
public class JwtSecretKey {
private final JwtConfig jwtConfig;
#Autowired
public JwtSecretKey(JwtConfig jwtConfig) {
this.jwtConfig = jwtConfig;
}
#Bean
public SecretKey secretKey() {
return Keys.hmacShaKeyFor(jwtConfig.getSecretKey().getBytes());
}
}
JwtConfig class
package com.example.demo.jwt;
import com.google.common.net.HttpHeaders;
import org.springframework.boot.context.properties.ConfigurationProperties;
#ConfigurationProperties(prefix = "application.jwt")
public class JwtConfig {
private String secretKey;
private String tokenPrefix;
private Integer tokenExpirationAfterDays;
public JwtConfig() {}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public String getTokenPrefix() {
return tokenPrefix;
}
public void setTokenPrefix(String tokenPrefix) {
this.tokenPrefix = tokenPrefix;
}
public Integer getTokenExpirationAfterDays() {
return tokenExpirationAfterDays;
}
public void setTokenExpirationAfterDays(Integer tokenExpirationAfterDays) {
this.tokenExpirationAfterDays = tokenExpirationAfterDays;
}
Annotate your JwtConfig class with #Configuration
#Configuration
#ConfigurationProperties(prefix = "application.jwt")
public class JwtConfig {
See in Javadocs:
Annotation for externalized configuration. Add this to a class
definition or a #Bean method in a #Configuration class if you want to
bind and validate some external Properties (e.g. from a .properties
file).
Reference: https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/context/properties/ConfigurationProperties.html

Java Spring #autowire not working in test class [duplicate]

This question already has an answer here:
Why autowiring spring repositories doesn't work?
(1 answer)
Closed 2 years ago.
I've a test class which autowires the CatalogDao class. But the CatalogDao class is not autowired. The value is null;
Test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {PersistenceConfig.class})
public class CatalogDaoIT {
#Autowired
private CatalogDao catalogDao;
#Test
public void saveCatalog_readSame_foundOne() {
// arrange
Catalog catalog = new Catalog();
Config class
package ch.matica.platform.persistence.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
#Configuration
#PropertySource("classpath:application.properties")
#ComponentScan(basePackages = "ch.matica.platform.persistence")
public class PersistenceConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertiesResolver() {
return new PropertySourcesPlaceholderConfigurer();
}
}
The DAO class
package ch.matica.platform.persistence;
import java.util.Collection;
...
#Repository
public class CatalogDao {
...
Can you change your code to this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {PersistenceConfig.class})
public class CatalogDaoIT {
#Autowired
private CatalogDao catalogDao;
//autowire by type, a private field and a setter
#Autowired
public void setCatalogDao(CatalogDao cd){
this.catalogDao=cd;
}
#Test
public void saveCatalog_readSame_foundOne() {
// arrange
Catalog catalog = new Catalog();
I think this will help.
For me this worked
#SpringBootTest
public class CatalogDaoIT {
....
}

Loading a random class using reflection and have it register as a component in springboot

I have a random class in a random package that is loaded through reflection after the app launches, is there a way for it to be registered as a component under springboot and have annotations such as #Autowired and #Value etc work for that class.
It works when it is in the same package at launch time, but if introduce it thorough another jar at runtime (same package or not) it doesn't work.
Below are samples that don't work even if it is in the same jar. I can't change the app's configuration - it would defeat the "random package/random class" objective.
Code in Spring boot application package
package sample.app
#SpringBootApplication
public class Application {
public static void main(String[] args) {
// Code that starts app
//
//
try {
Thread.sleep(7000);
Class test = Class.forName("test.Test", true, Application.class.getClassLoader());
System.out.println(test.getMethod("getName").invoke(null)); //NPE
System.out.println(test.getMethod("getProfiles").invoke(null)); //NPE
} catch (Throwable t) {
t.printStackTrace();
}
}
}
Test.java
package test;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.DependsOn;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
#DependsOn("blaaaaaaaah")
#ComponentScan
public class Test {
#DependsOn("blaaaaaaaah")
public static String getName() {
return SpringGetter.instance.getApplicationName();
}
#DependsOn("blaaaaaaaah")
public static String[] getProfiles() {
String[] profiles = SpringGetter.instance.getEnv().getActiveProfiles();
if (profiles == null || profiles.length == 0) {
profiles = SpringGetter.instance.getEnv().getDefaultProfiles();
}
return profiles;
}
}
SpringGetter.java
package test;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
#Component("blaaaaaaaah")
public class SpringGetter implements InitializingBean {
public static SpringGetter instance;
#Value("${spring.application.name}")
private String applicationName;
#Autowired
private Environment env;
public SpringGetter() {
System.out.println("consASFJEFWEFJWDNFWJVNJSBVJWNCJWBVJNVJNVJSNJSNCSDJVNSVJtruct");
}
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public Environment getEnv() {
return env;
}
public void setEnv(Environment env) {
this.env = env;
}
#PostConstruct
public void setInstance() {
instance = this;
}
#Override
public void afterPropertiesSet() throws Exception {
instance = this;
}
}
EDIT:
I managed to dynamically create the SpringGetter class as part of the same package as the Application class(the one with the #SpringBootApplication). I got Test.java to point to that dynamic class and yet no luck.
To simply inject fields into a POJO as if it were a Spring-managed bean, you can use something like the following:
#Component
public class BeanInitializer implements ApplicationContextAware {
private AutowireCapableBeanFactory beanFactory;
#Override
public void setApplicationContext(final ApplicationContext applicationContext) {
beanFactory = applicationContext.getAutowireCapableBeanFactory();
}
public void initializeObject(Object pojo) {
beanFactory.autowireBean(pojo);
}
}
Note, however, that this only injects fields marked as #Autowired or #Injected. It does not create proxies that honor method interception strategies based on e.g. #Transactional, #Async, etc.
If you're using Spring 5, have a look at the registerBean() method from GenericApplicationContext. You can find an example here: https://www.baeldung.com/spring-5-functional-beans
The issue in your Test class may also be that you're not loading the Spring Boot context from the main class. You can use the SpringBootTest annotation for this.

How do I make Autowired work inside a Configuration class?

I'm trying to autowire an attribute (myService) which is tagged as a #Service, inside a #Configuration class, but I get a NullPointer.
If instead, I autowire myService in non-configuration classes, I have no issues.
Here's the #Service I'm having issues autowiring:
package com.myapp.resources;
#Service
class MyService {
public List<String> getRoutingKeys() {
List<String> routingKeys;
//Do stuff
return routingKeys;
}
public String aMethod() {
return "hello";
}
}
Here's the #Configuration class where I can't autowire the Service
package com.myapp.messaging;
import com.myapp.resources;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
#Configuration
public class RabbitConfiguration {
private List<String> routingKeys = writeRoutingKeys();
#Autowired
private MyService myService;
private List<String> writeRoutingKeys() {
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: true!!!
return myService.getRoutingKeys(); //here I get a NullPointer
}
//Methods with bean declarations for RabbitMQ
}
If it helps, here's my mainclass:
package com.myapp;
import com.myapp.resources;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import java.util.List;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext appContext = SpringApplication.run(Application.class, args);
MyService myService = (MyService) appContext.getBean(MyService.class);
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: false
//Do stuff
}
}
If it helps, here's a different class (a #RestController) where I'm able to autowire the service
package com.myapp.resources;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class MyController {
#Autowired
private MyService myService;
#GetMapping("/endpoint")
public String myRestMethod() {
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: false
return myService.aMethod();
}
}
I've also tried adding the #ComponentScan in the Configuration class, but I still get a NullPointer
package com.myapp.messaging;
//list of imports...
#Configuration
#ComponentScan("com.myapp.demo")
public class RabbitConfiguration {
#Autowired
private MyService myService;
//...
}
Spring will only inject the dependencies after or when a bean is instantiated (Depending if constructor injection is used or not). However , you are now accessing the dependency MyService during the field initialisation which happens before initialising a bean .Hence , it cannot access MyService during field initialisation as it is not injected yet.
You can simply fix it by changing to use constructor injection and initialise routingKeys inside a constructor at the same time :
#Configuration
public class RabbitConfiguration {
private List<String> routingKeys ;
private MyService myService;
#Autowired
public RabbitConfiguration(MyService myService){
this.myService = myService
this.routingKeys = writeRoutingKeys();
}
private List<String> writeRoutingKeys() {
return myService.getRoutingKeys();
}
}
Or simply :
#Autowired
public RabbitConfiguration(MyService myService){
this.myService = myService
this.routingKeys = myService.getRoutingKeys();
}
I would suggest injecting the service through any #Bean creation method that needs it:
#Bean
public MyBean create(MyService myService)
and then pass the service into the writeRoutingKeys(MyService myService) method to process it accordingly.
Per documentation:
#Configuration classes are processed quite early during the
initialization of the context and forcing a dependency to be injected
this way may lead to unexpected early initialization. Whenever
possible, resort to parameter-based injection as in the example above.

Autowire in An Nonbean Class using AspectJ

AppConfig contains Java Configuration.
package com.wh;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableLoadTimeWeaving;
import org.springframework.context.annotation.EnableLoadTimeWeaving.AspectJWeaving;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.aspectj.EnableSpringConfigured;
#Configuration
#EnableSpringConfigured
#EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
public class AppConfig {
#Bean
#Lazy
public EchoService echoService(){
return new EchoService();
}
#Bean
public InstrumentationLoadTimeWeaver loadTimeWeaver() throws Throwable {
InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
return loadTimeWeaver;
}
}
Service Class
package com.wh;
import org.springframework.stereotype.Service;
#Service
public class EchoService {
public void echo( String s ) {
System.out.println( s );
}
}
EchoDelegateService is the Non Bean class in which we have Autowired The required Bean.
We expect that the EchoService should get autowired.
Problem : EchoService not getting autowired. Gives an Null Pointer exception.
package com.wh;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
#Configurable( preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false )
public class EchoDelegateService {
#Autowired
private EchoService echoService;
public void echo( String s ) {
echoService.echo( s );
}
}
Main Class where we are calling method of NonBean Class.
package com.wh;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class);
new EchoDelegateService().echo("hihi, it works...");
}
}
Your question already includes the answer: "... in a non-bean class". This simply does not work. All the autowiring, aspect resolving and whatever is to that, only works for beans. Thus, you definitely need to construct your EchoDelegateService via the spring factory:
EchoDelegateService myService = ctx.getBean(EchoDelegateService.class);
myService.echo("this should really work now");

Categories

Resources