How to load the properties from application.properties in Mockito test - java

I am trying to write a unit test case to test the method, but I encounter a problem.
here is the sample code:
MyService1
#Service
public class MyService1 {
#Autowired
private ServiceProperties serviceProperties;
public void getMyLanguage(){
String language = serviceProperties.getLocale().getLanguage();
printSomething(language);
}
private void printSomething(String input){
System.out.print("your current language is " + input);
}
}
ServiceProperties
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Locale;
#ConfigurationProperties(prefix = "conversation")
public class ServiceProperties {
private ServiceProperties(){};
private Locale locale;
public Locale getLocale(){
return locale;
}
}
application.properties
conversation.locale=en_US
Here is my test case:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
#RunWith(MockitoJUnitRunner.class)
public class MyService1Test {
#Mock
private ServiceProperties serviceProperties;
#InjectMocks
private MyService1 myService1;
#Test
public void getMyLanguage(){
when(serviceProperties.getLocale().getLanguage()).thenReturn("EN");
myService1.getMyLanguage();
verify(myService1).getMyLanguage();
}
}
the test will trigger nullpointerexception, because the properties for locale are not loaded in test, if I don't want to start the server(use #SpringBootTest annotation) to load the context, is there any way to solve this problem, can anyone help?

The problem is at this line:
when(serviceProperties.getLocale().getLanguage()).thenReturn("EN");
Because serviceProperties is mocked, serviceProperties.getLocale() is equal to null. So you get NullPointerException when serviceProperties.getLocale().getLanguage() is called.
One workaround would be as follows:
#RunWith(MockitoJUnitRunner.class)
public class MyService1Test {
#Mock
private ServiceProperties serviceProperties;
#InjectMocks
private MyService1 myService1;
#Test
public void getMyLanguage(){
when(serviceProperties.getLocale()).thenReturn(new Locale("EN"));
myService1.getMyLanguage();
verify(myService1).getMyLanguage();
}
}

Field injection is not convenient for testing. You can use constructor injection
#Service
public class MyService {
private final ServiceProperties serviceProperties;
#Autowired
public MyService(ServiceProperties serviceProperties) {
this.serviceProperties = serviceProperties;
}
//...
}
And then you will be able to inject mocks before each test
#RunWith(MockitoJUnitRunner.class)
public class MyService1Test {
#Mock
private ServiceProperties serviceProperties;
private MyService1 myService1;
#Before
public void createService(){
myService1 = new MyService1(serviceProperties);
}
}

Related

NullPointerException in Junit 5 #MockBean

I wrote a JUnit 5 test for my service in my Spring Boot application.
I used #MockBean to mock PasswordEncoder and other beans but I obtain a NullPointerException.
I always obtain a NullPointerException during the when call :
when(compteRepository.getByLogin(anyString())).thenReturn(Optional.of(acc));
Service
package com.compte.application.impl;
import com.compte.application.CompteService;
import com.compte.domain.exceptions.EntityNotFoundExcpetion;
import com.compte.domain.model.Compte;
import com.compte.domain.model.CompteUpdatedData;
import com.compte.domain.repository.CompteRepository;
import com.compte.domain.utils.CompteUtil;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.time.LocalDate;
import java.util.Optional;
/**
* #author mbint
*/
#AllArgsConstructor
public class CompteServiceImpl implements CompteService{
private final static Logger LOGGER = LoggerFactory.getLogger(CompteService.class);
private CompteRepository CompteRepository;
private PasswordEncoder passwordEncoder;
#Override
public Optional<Compte> getByLogin(String login) {
return CompteRepository.getByLogin(login);
}
#Override
public void update(final Long id, CompteUpdatedData updatedData) {
Optional<Compte> optional = CompteRepository.getById(id);
if(optional.isPresent()) {
Compte Compte = optional.get();
Compte.setFirstName(updatedData.getFirstName());
Compte.setLastName(updatedData.getLastName());
CompteRepository.save(Compte);
} else {
throw new EntityNotFoundExcpetion("Compte: " + id + " not found !!");
}
}
}
Junit Test
package com.compte.application;
import com.compte.application.impl.CompteServiceImpl;
import com.compte.domain.model.Compte;
import com.compte.domain.model.CompteUpdatedData;
import com.compte.domain.repository.compteRepository;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static org.mockito.Mockito.*;
/**
* #author mbint
*/
public class CompteServiceImplTest {
private final static String PASSWORD = "Passw00rd";
#MockBean
private compteRepository compteRepository;
#MockBean
private PasswordEncoder passwordEncoder;
private CompteService CompteService = new CompteServiceImpl(compteRepository, passwordEncoder);
#DisplayName(("Should return existing user"))
#Test
private void given_login_then_return_existing_user() {
Compte acc = Compte.builder().id(1L)
.firstName("Luc")
.lastName("JOJO")
.login("xxx#gmail.com")
.password("xxxxxxxxxxxxxxx")
.build();
when(compteRepository.getByLogin(anyString())).thenReturn(Optional.of(acc));
Optional<Compte> optional = CompteService.getByLogin("xxx#gmail.com");
Compte Compte = optional.get();
Assertions.assertSame(1L, acc.getId());
Assertions.assertSame("xxx#gmail.com", Compte.getLogin());
}
#DisplayName("Should update existing user")
#Test
public void given_edited_Compte_then_update_user() {
Compte acc = Compte.builder().id(1L)
.firstName("Luc")
.lastName("JOJO")
.email("xxx#gmail.com")
.password("xxxxxxxxxxxxxxx")
.build();
when(compteRepository.getById(anyLong())).thenReturn(Optional.of(acc));
CompteUpdatedData updatedData = CompteUpdatedData.builder()
.firstName("Moos")
.lastName("Man")
.build();
CompteService.update(1L, updatedData);
Assertions.assertSame("Moos", acc.getFirstName());
}
private List<Compte> getComptes() {
List<Compte> Comptes = new ArrayList<>();
Compte acc1 = Compte.builder()
.id(1L)
.firstName("Luc")
.lastName("JOJO")
.email("xxx#gmail.com")
.login("xxx#gmail.com")
.build();
Comptes.add(acc1);
Compte acc2= Compte.builder()
.id(2L)
.firstName("Jean")
.lastName("KELLY")
.email("jean.kelly#gmail.com")
.login("jean.kelly#gmail.com")
.build();
Comptes.add(acc2);
Compte acc3= Compte.builder()
.id(3L)
.firstName("Marc")
.lastName("BARBY")
.email("marc.barby#gmail.com")
.login("marc.barby#gmail.com")
.build();
Comptes.add(acc3);
return Comptes;
}
}
Spring boot application
package com.compte;
import com.compte.application.CompteService;
import com.compte.application.impl.CompteServiceImpl;
import com.compte.domain.repository.CompteRepository;
import com.compte.infrastructure.repository.database.CompteDBRepositiry;
import com.ombsc.bargo.common.config.SwaggerConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.hateoas.client.LinkDiscoverer;
import org.springframework.hateoas.client.LinkDiscoverers;
import org.springframework.hateoas.mediatype.collectionjson.CollectionJsonLinkDiscoverer;
import org.springframework.plugin.core.SimplePluginRegistry;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.ArrayList;
import java.util.List;
#ComponentScan({"com.compte.interfaces.interfaces"})
#SpringBootApplication
#Import({SwaggerConfig.class})
public class CompteApplication {
public static void main(String[] args) {
SpringApplication.run(CompteApplication.class, args);
}
#Bean
public CompteRepository getRepository() {
return new CompteDBRepositiry();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public CompteService CompteService(CompteRepository repository, PasswordEncoder passwordEncoder) {
return new CompteServiceImpl(repository, passwordEncoder);
}
#Bean
public LinkDiscoverers discovers() {
List<LinkDiscoverer> plugins = new ArrayList<>();
plugins.add(new CollectionJsonLinkDiscoverer());
return new LinkDiscoverers(SimplePluginRegistry.create(plugins));
}
}
The mocks need to be initialized before they can be used. There are several options to do this.
The first option would be to use #SpringExtension which will initialize the mocks annotated with #MockBean:
#ExtendWith(SpringExtension.class)
public class CompteServiceImplTest {
#Autowired
private CompteService CompteService;
#MockBean
private compteRepository compteRepository;
// ...
}
This will make sure that the repository bean is mocked before the service bean is autowired.
However, since you are writing a unit test for the service, you don't need the Spring extension at all. The second option is to use #Mock instead of #MockBean, and call #InjectMocks in conjunction with the MockitoExtension for constructing the service under test:
#ExtendWith(MockitoExtension.class)
public class CompteServiceImplTest {
#InjectMocks
private CompteService CompteService;
#Mock
private compteRepository compteRepository;
// ...
}
Alternatively, you could just call MockitoAnnotations.initMocks(), which will initialize the mocks annotated with #Mock, and use constructor injection for your service:
public class CompteServiceImplTest {
private CompteService CompteService;
#Mock
private compteRepository compteRepository;
#BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
CompteService = new CompteServiceImpl(compteRepository, ...);
}
// ...
}
Finally, you could do it all without annotations just by calling Mockito.mock() directly:
public class CompteServiceImplTest {
private compteRepository compteRepository;
#BeforeEach
void setUp() {
compteRepository = Mockito.mock();
CompteService = new CompteServiceImpl(compteRepository, ...);
}
// ...
}

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.

How to test an aspect with SpringBootTest?

I created a simple aspect in Spring using Spring Boot 2.1.6.RELEASE.
It basically logs the total time spent on a method.
#Aspect
#Component
public class TimeLoggerAspect {
private static final Logger log = LoggerFactory.getLogger(TimeLoggerAspect.class);
#Around("#annotation(demo.TimeLogger)")
public Object methodTimeLogger(ProceedingJoinPoint joinPoint)
throws Throwable {
long startTime = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
long totalTime = System.currentTimeMillis() - startTime;
log.info("Method " + joinPoint.getSignature() + ": " + totalTime + "ms");
return proceed;
}
}
the aspect is triggered by a TimeLogger annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface TimeLogger {
}
and is used in a component like this
#Component
public class DemoComponent {
#TimeLogger
public void sayHello() {
System.out.println("hello");
}
}
A spring boot demo application will invoke sayHello via the run method of the CommandLineRunner interface.
#SpringBootApplication
public class DemoApplication implements CommandLineRunner {
#Autowired
private DemoComponent demoComponent;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
demoComponent.sayHello();
}
}
For completeness, I add my modifications in build.gradle: adding libraries for aop, spring test and jupiter (junit).
compile("org.springframework.boot:spring-boot-starter-aop")
testCompile("org.springframework.boot:spring-boot-starter-test")
testCompile("org.junit.jupiter:junit-jupiter-api")
testRuntime("org.junit.jupiter:junit-jupiter-engine")
Running the application will output (trimmed for readability)
hello
... TimeLoggerAspect : Method void demo.DemoComponent.sayHello(): 4ms
So far, so good. Now I create a test based on #SpringBootTest annotation and jupiter.
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = {DemoComponent.class, TimeLoggerAspect.class})
public class DemoComponentFailTest {
#Autowired
private DemoComponent demoComponent;
#Test
public void shouldLogMethodTiming() {
demoComponent.sayHello();
}
}
and here I get the output
hello
No output from the TimeLoggerAspect, since it seems it is not being triggered.
Is something missing to trigger the aspect in the test? Or are there other ways of testing the aspect in spring boot?
I had similar problem. My Aspect is listening on controller methods. To get it activated, importing the AnnotationAwareAspectJAutoProxyCreator made the trick:
#RunWith(SpringRunner.class)
#Import(AnnotationAwareAspectJAutoProxyCreator.class) // activate aspect
#WebMvcTest(MyController.class)
public class MyControllerTest {
...
}
You have to put #EnableAspectJAutoProxy with your file #Configuration that declares the bean with #Aspect.
#Aspect
#Configuration
#EnableAspectJAutoProxy
public class TimeLoggerAspect {
private static final Logger log = LoggerFactory.getLogger(TimeLoggerAspect.class);
#Around("#annotation(demo.TimeLogger)")
public Object methodTimeLogger(ProceedingJoinPoint joinPoint)
throws Throwable {
long startTime = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
long totalTime = System.currentTimeMillis() - startTime;
log.info("Method " + joinPoint.getSignature() + ": " + totalTime + "ms");
return proceed;
}
}
I think that will do the work.
You need to start an #SpringBootApplication. However, it does not have to be the one you use to start your app in production. It can be a special one for this test only and can be in your test sources root not your src.
#SpringBootApplication
#ComponentScan(basePackageClasses = {DemoComponent.class, TimeLoggerAspect.class})
public class SpringBootTestMain {
public static void main(String[] args) {
SpringApplication.run(SpringBootTestMain.class, args);
}
}
Then in your test this is the only class you need to list.
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = SpringBootTestMain.class)
public class DemoComponentFailTest {
Another solution that seems to work is adding AnnotationAwareAspectJAutoProxyCreator in classes of #SpringBootTest, although I am not quite certain why.
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = { DemoComponent.class,
TimeLoggerAspect.class,
AnnotationAwareAspectJAutoProxyCreator.class })
public class DemoComponentFailTest {
#Autowired
private DemoComponent demoComponent;
#Test
public void shouldLogMethodTiming() {
demoComponent.sayHello();
}
}
When I had to test an aspect, I used the approach below.
#SpringBootTest
#ContextConfiguration(classes = {MyAspectImpl.class, MyAspectTest.TestConfiguration.class})
#EnableAspectJAutoProxy
public class MyAspectTest {
#org.springframework.boot.test.context.TestConfiguration
static class TestConfiguration {
#Bean
public MyAspectTestClass myAspectTestClass() {
return new MyAspectTestClass();
}
}
#Autowired
private MyAspectTestClass target;
#Test
public void testCorrectlySetsPoolNameUsingMethodParameter() {
target.testMethod();
}
#NoArgsConstructor
private static class MyAspectTestClass {
#MyAspect
public void testMethod() {
//Add some logic here
}
}
}

Spring test service class mocking utility class- Junit and Mockito

I want to write test cases for service layer of spring framework using Junit + Mockito.
How to call the actual service layer method using my ServiceTest class, If i mock the ServiceTest class then it's object wont execute the actual service method code because it wont get the object to call it's methods and if I try with the Spy still it was not working, I tried this example
still I not able to execute the test cases.
MyService.java
#Service
public class MyService{
#Autowired
Utility utility;
public String showResult(){
String result = utility.getName();
return result;
}
}
MyServiceTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader=AnnotationConfigWebContextLoader.class)
#WebAppConfiguration
public class MyServiceTest {
#Autowired
MyService myService;
#Autowired
Utility utility;
#Test
public void testShowResult() throws Exception {
assertEquals("Test",myService.showResult());
}
#Configuration
static class MykServiceTestContextConfiguration {
#Bean
public MyService myService() {
return new MyService();
}
#Bean
public Utility utility() {
return Mockito.mock(Utility.class);
}
}
}
You have to first mock the Utility class and then have to invoke it before calling your #Test using MockitoAnnotations.initMocks(this) as follows:
MyServiceTest.java
import static org.mockito.Mockito.when;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.AnnotationConfigWebContextLoader;
import org.springframework.test.context.web.WebAppConfiguration;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = AnnotationConfigWebContextLoader.class)
#WebAppConfiguration
public class MyServiceTest {
#InjectMocks
private MyService myService;
#Mock
private Utility utility;
#Before
public void setupMock() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testShowResult() throws Exception {
when(utility.getName()).thenReturn("Test");
Assert.assertEquals("Test", myService.showResult());
}
#Configuration
static class MykServiceTestContextConfiguration {
#Bean
public MyService myService() {
return new MyService();
}
#Bean
public Utility utility() {
return new Utility();
}
}
}
MyService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class MyService {
#Autowired
private Utility utility;
public String showResult() {
String result = utility.getName();
return result;
}
}
Utility.java
import org.springframework.stereotype.Component;
#Component
public class Utility {
public String getName() {
return "hello";
}
}
Make use of #Spy
When spy is called, then actual method of real object is called.
https://www.tutorialspoint.com/mockito/mockito_spying.htm
please go through the tutorial
This worked for me
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
#WebAppConfiguration
public class MyServiceTest {
#Spy
MyService myService;
#Test
public void testShowResult() throws Exception {
assertEquals("Test",myService.showResult());
}
#Service
public class MyService{
public String showResult(){
return "Test";
}
}
}
still having issues share the spring version you are using
How about using #MockBean? It suits Spring + JUnit and, probably you need to implement mock behavior.
I guess that Utility.getName() return "Test" in the test case.
The following is the test code I tried.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = AnnotationConfigWebContextLoader.class)
#WebAppConfiguration
public class MyServiceTest {
#Autowired
MyService myService;
#MockBean
Utility utility;
#Test
public void testShowResult() throws Exception {
Mockito.when(utility.getName()).thenReturn("Test");
assertEquals("Test", myService.showResult());
}
#Configuration
static class MykServiceTestContextConfiguration {
#Bean
public MyService myService() {
return new MyService();
}
}
}

Nullpointer when using #Autowire

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 {
}

Categories

Resources