I am trying to do integration testing in spring boot application using JUnit5 but it gives me Null Pointer Exception at that line String response = restTemplate.getForObject("/v1/students", String.class);. All unit tests are working fine but I can't figure out what's wrong with the integration test.
Here is the Integration Test class:
package com.demo.student.demo;
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class DemoApplicationTest {
#Autowired
private TestRestTemplate restTemplate;
#Test
public void contextLoads() throws Exception {
String response = restTemplate.getForObject("/v1/students", String.class);
JSONAssert.assertEquals("[{'id':1,'email':'test#test.test'}]", response, false);
}
}
Here is the stacktrace:
java.lang.NullPointerException
at com.demo.student.demo.DemoApplicationTest.contextLoads(DemoApplicationTest.java:18)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:513)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:170)
at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:166)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:113)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:113)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:121)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:121)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:121)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:121)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
And the REST endpoint I am testing against:
package com.demo.student.demo.service;
import com.demo.student.demo.entity.Student;
import com.demo.student.demo.exception.StudentNotFoundException;
import com.demo.student.demo.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class StudentServiceImpl implements StudentService {
private StudentRepository studentRepository;
#Autowired
public StudentServiceImpl(StudentRepository studentRepository){
this.studentRepository = studentRepository;
}
#Override
public List<Student> findAl() {
return studentRepository.findAll();
}
#Override
public Student findById(long id) {
return studentRepository.findById(id).orElseThrow(() -> new StudentNotFoundException(id));
}
#Override
public Student saveOrUpdate(Student student) {
studentRepository.save(student);
return student;
}
#Override
public void deleteById(long id) {
if(this.findById(id) != null)
studentRepository.deleteById(id);
}
}
Oh I forgot to add the plugin for failsafe in the pom.xml. And add the #ExtendWith(SpringExtension.class) at the class level. My bad!
Related
I'm trying this tutorial from a book where there's an api running and when the application with the redis code gets called, it's suppose to output the information from the api. However, this is the error I get when I run the application:
org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to localhost/<unresolved>:6379
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1689) ~[spring-data-redis-2.6.3.jar:2.6.3]
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1597) ~[spring-data-redis-2.6.3.jar:2.6.3]
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1383) ~[spring-data-redis-2.6.3.jar:2.6.3]
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1366) ~[spring-data-redis-2.6.3.jar:2.6.3]
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:1093) ~[spring-data-redis-2.6.3.jar:2.6.3]
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getConnection(LettuceConnectionFactory.java:421) ~[spring-data-redis-2.6.3.jar:2.6.3]
at com.demo.springdataexample.demo.PlaneFinderPoller.pollPlanes(PlaneFinderPoller.java:25) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) ~[spring-context-5.3.18.jar:5.3.18]
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.3.18.jar:5.3.18]
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[na:na]
at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) ~[na:na]
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to localhost/<unresolved>:6379
at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:78) ~[lettuce-core-6.1.8.RELEASE.jar:6.1.8.RELEASE]
at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:56) ~[lettuce-core-6.1.8.RELEASE.jar:6.1.8.RELEASE]
at io.lettuce.core.AbstractRedisClient.getConnection(AbstractRedisClient.java:330) ~[lettuce-core-6.1.8.RELEASE.jar:6.1.8.RELEASE]
at io.lettuce.core.RedisClient.connect(RedisClient.java:216) ~[lettuce-core-6.1.8.RELEASE.jar:6.1.8.RELEASE]
at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection$1(StandaloneConnectionProvider.java:115) ~[spring-data-redis-2.6.3.jar:2.6.3]
at java.base/java.util.Optional.orElseGet(Optional.java:364) ~[na:na]
at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:115) ~[spring-data-redis-2.6.3.jar:2.6.3]
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1595) ~[spring-data-redis-2.6.3.jar:2.6.3]
... 17 common frames omitted
Below is the code:
Main class:
package com.demo.springdataexample.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
#SpringBootApplication
public class SburRedisApplication {
#Bean
public RedisOperations<String, Aircraft>
redisOperations(RedisConnectionFactory factory) {
Jackson2JsonRedisSerializer<Aircraft> serializer =
new Jackson2JsonRedisSerializer<>(Aircraft.class);
RedisTemplate<String, Aircraft> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setDefaultSerializer(serializer);
template.setKeySerializer(new StringRedisSerializer());
return template;
}
public static void main(String[] args) {
SpringApplication.run(SburRedisApplication.class, args);
}
}
PlaneFinderPoller.java
package com.demo.springdataexample.demo;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
#EnableScheduling
#Component
public class PlaneFinderPoller {
private WebClient webclient =
WebClient.create("http://localhost:7634/aircraft");
private final RedisConnectionFactory connectionFactory;
private final RedisOperations<String, Aircraft> redisOperations;
public PlaneFinderPoller(RedisConnectionFactory connectionFactory,
RedisOperations<String, Aircraft> redisOperations)
{
this.connectionFactory = connectionFactory;
this.redisOperations = redisOperations;
}
#Scheduled(fixedRate = 1000)
private void pollPlanes(){
connectionFactory.getConnection().serverCommands().flushDb();
webclient.get()
.retrieve()
.bodyToFlux(Aircraft.class)
.filter(plane -> !plane.getReg().isEmpty())
.toStream()
.forEach(ac -> redisOperations.opsForValue().set(ac.getReg(), ac));
redisOperations.opsForValue()
.getOperations()
.keys("*")
.forEach(ac -> System.out.println(redisOperations.opsForValue().get(ac)));
}
}
Aircraft.java
I find that book author in this issue says running redis:
https://github.com/mkheck/SpringBootUpAndRunning/issues/1
I am new to spring batch framework. I am making a spring boot program to read from a XML file and store it in the MySQL database.
But the application is throwing the following error.
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:153) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader$$FastClassBySpringCGLIB$$ebb633d0.invoke(<generated>) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.batch.item.xml.StaxEventItemReader$$EnhancerBySpringCGLIB$$1a0f0ba5.open(<generated>) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:311) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:205) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:410) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:319) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:147) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at com.sun.proxy.$Proxy39.run(Unknown Source) ~[na:na]
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-2.3.2.RELEASE.jar:2.3.2.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173) ~[spring-boot-autoconfigure-2.3.2.RELEASE.jar:2.3.2.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160) ~[spring-boot-autoconfigure-2.3.2.RELEASE.jar:2.3.2.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155) ~[spring-boot-autoconfigure-2.3.2.RELEASE.jar:2.3.2.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150) ~[spring-boot-autoconfigure-2.3.2.RELEASE.jar:2.3.2.RELEASE]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:786) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:776) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
at com.swt.helloworld.HelloworldApplication.main(HelloworldApplication.java:41) ~[classes/:na]
Caused by: java.lang.IllegalArgumentException: The Resource must not be null.
at org.springframework.util.Assert.notNull(Assert.java:201) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.batch.item.xml.StaxEventItemReader.doOpen(StaxEventItemReader.java:205) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:150) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE]
... 43 common frames omitted
I am not able to understand why the resource is null error is coming.I have also attached my BatchConfiguration.java file below:
package com.swt.helloworld.config;
import com.swt.helloworld.model.Product;
import com.swt.helloworld.writer.ConsoleItemWriter;
import com.swt.helloworld.listener.HwJobExecutionListener;
import com.swt.helloworld.listener.HwStepExecutionListener;
import com.swt.helloworld.processor.InMemeItemProcessor;
import com.swt.helloworld.reader.InMemReader;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.batch.item.file.transform.LineTokenizer;
import org.springframework.batch.item.xml.StaxEventItemReader;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileSystemResource;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
#EnableBatchProcessing
#Configuration
public class BatchCondifguration {
#Autowired
private JobBuilderFactory jobs;
#Autowired
private StepBuilderFactory steps;
#Autowired
private HwJobExecutionListener hwJobExecutionListener;
#Autowired
private HwStepExecutionListener hwStepExecutionListener;
#Autowired
private InMemeItemProcessor inMemeItemProcessor;
public Tasklet helloWorldTasklet(){
return (new Tasklet() {
#Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("Hello world " );
return RepeatStatus.FINISHED;
}
});
}
#Bean
public Step step1(){
return steps.get("step1")
.listener(hwStepExecutionListener)
.tasklet(helloWorldTasklet())
.build();
}
#Bean
public InMemReader reader(){
return new InMemReader();
}
#StepScope
#Bean
public StaxEventItemReader xmlItemReader(
#Value( "#{jobParameters['fileInput']}" )
FileSystemResource inputFile
){
// where to read the xml file
StaxEventItemReader reader = new StaxEventItemReader();
reader.setResource(inputFile);
//need to let reader to know which tags describe the domain object
reader.setFragmentRootElementName("product");
// tell reader how to parse XML and which domain object to be mapped
reader.setUnmarshaller(new Jaxb2Marshaller(){
{
setClassesToBeBound(Product.class);
}
});
return reader;
}
#StepScope
#Bean
public FlatFileItemReader flatFileItemReader(
#Value( "#{jobParameters['fileInput']}" )
FileSystemResource inputFile ){
FlatFileItemReader reader = new FlatFileItemReader();
// step 1 let reader know where is the file
reader.setResource( inputFile );
//create the line Mapper
reader.setLineMapper(
new DefaultLineMapper<Product>(){
{
setLineTokenizer( new DelimitedLineTokenizer() {
{
setNames( new String[]{"prodId","productName","prodDesc","price","unit"});
setDelimiter("|");
}
});
setFieldSetMapper( new BeanWrapperFieldSetMapper<Product>(){
{
setTargetType(Product.class);
}
});
}
}
);
//step 3 tell reader to skip the header
reader.setLinesToSkip(1);
return reader;
}
#Bean
public Step step2(){
return steps.get("step2").
<Integer,Integer>chunk(3)
// .reader(flatFileItemReader( null ))
.reader(xmlItemReader(null))
.writer(new ConsoleItemWriter())
.build();
}
#Bean
public Job helloWorldJob(){
return jobs.get("helloWorldJob")
.incrementer(new RunIdIncrementer())
.listener(hwJobExecutionListener)
.start(step1())
.next(step2())
.build();
}
}
Following the stack trace, I think you need to check your "job parameter" named 'fileInput'. Enter the file path in your program parameter 'fileInput'.
Perhaps it works adding this part in you parameter when you run your batch application:
fileInput=/path/your/input/file
See futher at the Spring document.
I tried everything from my site but I am not able to solve this issue
last 4 days.
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property id found for type UserRegistration!
I use jpa and springboot in my application, but I don't know why face
this type of issue
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property id found for type UserRegistration!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:90) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:437) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:413) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.data.mapping.PropertyPath.lambda$from$0(PropertyPath.java:366) ~[spring-data-commons-2.5.1.jar:2.5.1]
at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:330) ~[na:na]
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:348) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:331) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:81) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.data.repository.query.parser.PartTree$OrPart.lambda$new$0(PartTree.java:249) ~[spring-data-commons-2.5.1.jar:2.5.1]
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) ~[na:na]
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na]
at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:250) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.data.repository.query.parser.PartTree$Predicate.lambda$new$0(PartTree.java:383) ~[spring-data-commons-2.5.1.jar:2.5.1]
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) ~[na:na]
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na]
at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:384) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:95) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:89) ~[spring-data-jpa-2.5.1.jar:2.5.1]
... 70 common frames omitted
I use custom query in my repository file
UserRegistration.kt
package com.userservice.userregistration.entity
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
#Entity
data class UserRegistration(
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
val userId:Long=-1,
val firstName:String="",
val lastName:String="",
val email:String="",
val departmentId:Long=-1,
)
UserRegistrationRepository.kt
package com.userservice.userregistration.repository
import com.userservice.userregistration.entity.UserRegistration
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
#Repository
interface UserRegistrationRepository : JpaRepository<UserRegistration,Long> {
fun findUserById(userId: Long?): UserRegistration?
}
UserRegistrationService.kt
package com.userservice.userregistration.service
import com.userservice.userregistration.VO.Department
import com.userservice.userregistration.VO.ResponseTemplateVO
import com.userservice.userregistration.entity.UserRegistration
import com.userservice.userregistration.repository.UserRegistrationRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate
#Service
class UserRegistrationService {
#Autowired
private lateinit var userRegistrationRepository: UserRegistrationRepository
#Autowired
private lateinit var restTemplate: RestTemplate
fun saveUserDetails(userRegistration: UserRegistration): UserRegistration {
return userRegistrationRepository.save(userRegistration)
}
fun getUserWithDepartment(userId: Long): ResponseTemplateVO {
val vo= ResponseTemplateVO()
val userRegistration:UserRegistration? = userRegistrationRepository.findUserById(userId)
val department: Department? =
restTemplate.getForObject("http://localhost:9001/departments/"+ userRegistration?.departmentId,
Department::class.java)
vo.userRegistration=userRegistration
if (department != null) {
vo.department=department
}
return vo
}
}
UserRegistrationController.kt
package com.userservice.userregistration.controller
import com.userservice.userregistration.VO.ResponseTemplateVO
import com.userservice.userregistration.entity.UserRegistration
import com.userservice.userregistration.service.UserRegistrationService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.*
#RestController
#RequestMapping("/users")
class UserRegistrationController {
#Autowired
private lateinit var userRegistrationService: UserRegistrationService
#PostMapping("/")
fun saveUserDetails(#ModelAttribute userRegistration:UserRegistration):UserRegistration{
return userRegistrationService.saveUserDetails(userRegistration)
}
#GetMapping("/{id}")
fun getUserWithDepartment(#PathVariable("id") userId:Long):ResponseTemplateVO{
return userRegistrationService.getUserWithDepartment(userId)
}
}
If I not use custom query on my Repository it show me another issue
"required UserRegistration found Optional" in my
userRegistrationService class
just change
#Repository
interface UserRegistrationRepository : JpaRepository<UserRegistration,Long> {
fun findUserById(userId: Long?): UserRegistration?
}
into
#Repository
interface UserRegistrationRepository : JpaRepository<UserRegistration,Long> {
fun findUserByUserId(userId: Long?): UserRegistration?
}
You don't have to declare separate query method for finding by ID, you can just add #Column annotation for you id property.
#Id
#Column("user_id") // or whatever it's called in the SQL table
#GeneratedValue(strategy = GenerationType.AUTO)
val userId:Long=-1
and then use standard method (Optional<T> findById(ID id);) inherited from JpaRepository
val userRegistration:UserRegistration? =
userRegistrationRepository.findById(userId).orElse(null)
I use Spring to store objects from the annotation based Object Mapping in a Neo4j database.
I have a generic class(InformationMutable) which contains as class attribute a list of another class(InformationEntry) of the same generic data type - private List<InformationEntry<T>> entries = new ArrayList<>();.
Full InformationMutable class:
package de.skillkiller.project.entity;
import lombok.*;
import org.springframework.data.neo4j.core.schema.Node;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
#EqualsAndHashCode(callSuper = true)
#Node
#Data
#ToString(callSuper = true)
#NoArgsConstructor
#AllArgsConstructor
public class InformationMutable<T extends Serializable> extends Information {
private List<InformationEntry<T>> entries = new ArrayList<>();
public void addEntry(T entry) {
entries.add(new InformationEntry<>(entry));
}
public void removeEntry(InformationEntry<T> entry) {
entries.remove(entry);
}
}
The goal is to have an object where in the list is only objects of the other class but with the same datatype in it. The InformationEntry class extends the datatype with uniform create and update dates.
Other required classes:
InformationEntry:
package de.skillkiller.project.entity;
import lombok.*;
import org.springframework.data.neo4j.core.schema.Node;
import java.io.Serializable;
#EqualsAndHashCode(callSuper = true)
#Node
#Data
#ToString(callSuper = true)
#NoArgsConstructor
#AllArgsConstructor
public class InformationEntry<T extends Serializable> extends BasicNode{
private T entry;
}
Information:
package de.skillkiller.project.entity;
import lombok.*;
import org.springframework.data.neo4j.core.schema.Node;
#EqualsAndHashCode(callSuper = true)
#Node
#Data
#ToString(callSuper = true)
#NoArgsConstructor
#AllArgsConstructor
public abstract class Information extends BasicNode{
private String information;
}
BasicNode:
package de.skillkiller.project.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.support.DateLong;
import java.util.Date;
#Data
#AllArgsConstructor
#NoArgsConstructor
public abstract class BasicNode {
#Id
#GeneratedValue
private Long id;
#DateLong
#LastModifiedDate
private Date changedAt = new Date();
#DateLong
#CreatedDate
private Date enteredAt = new Date();
}
InformationRepository:
package de.skillkiller.project.repository;
import de.skillkiller.project.entity.Information;
import org.springframework.data.neo4j.repository.Neo4jRepository;
public interface InformationRepository extends Neo4jRepository<Information, Long> {
}
Creation Process:
InformationMutable<Integer> informationMutable1 = new InformationMutable<>();
informationMutable1.addEntry(5);
informationMutable1.addEntry(15);
informationMutable1.setInformation("Test");
informationRepository.save(informationMutable1);
If I now create an object from the class InformationMutable, add values to the list and want to save it, I get the following error message:
ava.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:807) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:788) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:333) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.2.jar:2.4.2]
at de.skillkiller.project.ProjectApplication.main(ProjectApplication.java:19) ~[classes/:na]
Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.data.neo4j.core.mapping.Neo4jPersistentEntity.isNew(Object)" because "targetNodeDescription" is null
at org.springframework.data.neo4j.core.Neo4jTemplate.lambda$processNestedRelations$16(Neo4jTemplate.java:495) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithAssociations(BasicPersistentEntity.java:387) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.neo4j.core.Neo4jTemplate.processNestedRelations(Neo4jTemplate.java:452) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.neo4j.core.Neo4jTemplate.lambda$processNestedRelations$16(Neo4jTemplate.java:518) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithAssociations(BasicPersistentEntity.java:387) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.neo4j.core.Neo4jTemplate.processNestedRelations(Neo4jTemplate.java:452) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.neo4j.core.Neo4jTemplate.processRelations(Neo4jTemplate.java:442) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.neo4j.core.Neo4jTemplate.saveImpl(Neo4jTemplate.java:254) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.neo4j.core.Neo4jTemplate.save(Neo4jTemplate.java:225) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at org.springframework.data.neo4j.repository.support.SimpleNeo4jRepository.save(SimpleNeo4jRepository.java:131) ~[spring-data-neo4j-6.0.3.jar:6.0.3]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:289) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:524) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:531) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:156) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:131) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) ~[spring-data-commons-2.4.3.jar:2.4.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.3.jar:5.3.3]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.3.jar:5.3.3]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.3.jar:5.3.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.3.jar:5.3.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.3.jar:5.3.3]
at com.sun.proxy.$Proxy67.save(Unknown Source) ~[na:na]
at de.skillkiller.project.ProjectApplication.lambda$demo$0(ProjectApplication.java:57) ~[classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804) ~[spring-boot-2.4.2.jar:2.4.2]
... 5 common frames omitted
Nevertheless, is it somehow possible with Spring and Neo4j to store such a generic construct and read it out again?
The problem with your setting is that the InformationMutable declares a generic field that is seen by SDN as any other legit #Node annotated entity.
As a consequence SDN wants to create something like
(:Information:InformationMutable) -[:ENTRIES]-> (:InformationEntry) -[:ENTRY] -> (generic entry)
It does not see the generic field as a possible property and it cannot because the definition of the Integer type is done during runtime.
The green nodes on the right side are for example other real #Node entities that you could use and that contain a fixed Integer field, for example.
After looking around, I couldn't find any good solution to this.
My autowired didn't work as expected where it returns null. I've autowired this particular class in other classes and it works so it only doesn't work in constraintvalidator classes.
Error
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at
org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798)
~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at
org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:779)
~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at
org.springframework.boot.SpringApplication.run(SpringApplication.java:322)
~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at
org.springframework.boot.SpringApplication.run(SpringApplication.java:1237)
~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at
org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at
com.Alex.Mains.JpaApplication.main(JpaApplication.java:21)
~[classes/:na] Caused by:
org.springframework.transaction.TransactionSystemException: Could not
commit JPA transaction; nested exception is
javax.persistence.RollbackException: Error while committing the
transaction at
org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:543)
~[spring-orm-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743)
~[spring-tx-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)
~[spring-tx-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:632)
~[spring-tx-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:386)
~[spring-tx-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
~[spring-tx-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
~[spring-tx-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178)
~[spring-data-jpa-2.3.1.RELEASE.jar:2.3.1.RELEASE] at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE] at
com.sun.proxy.$Proxy93.save(Unknown Source) ~[na:na] at
com.Alex.Mains.UserRepositoryCommandLineRunner.run(UserRepositoryCommandLineRunner.java:26)
~[classes/:na] at
org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:795)
~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] ... 5 common frames
omitted Caused by: javax.persistence.RollbackException: Error while
committing the transaction at
org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:81)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:534)
~[spring-orm-5.2.7.RELEASE.jar:5.2.7.RELEASE] ... 21 common frames
omitted Caused by: javax.validation.ValidationException: HV000028:
Unexpected exception during isValid call. at
org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint(ConstraintTree.java:186)
~[hibernate-validator-6.1.5.Final.jar:6.1.5.Final] at
org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree.validateConstraints(SimpleConstraintTree.java:62)
~[hibernate-validator-6.1.5.Final.jar:6.1.5.Final] at
org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:75)
~[hibernate-validator-6.1.5.Final.jar:6.1.5.Final] at
org.hibernate.validator.internal.metadata.core.MetaConstraint.doValidateConstraint(MetaConstraint.java:130)
~[hibernate-validator-6.1.5.Final.jar:6.1.5.Final] at
org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:123)
~[hibernate-validator-6.1.5.Final.jar:6.1.5.Final] at
org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:555)
~[hibernate-validator-6.1.5.Final.jar:6.1.5.Final] at
org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:518)
~[hibernate-validator-6.1.5.Final.jar:6.1.5.Final] at
org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:488)
~[hibernate-validator-6.1.5.Final.jar:6.1.5.Final] at
org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:450)
~[hibernate-validator-6.1.5.Final.jar:6.1.5.Final] at
org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:400)
~[hibernate-validator-6.1.5.Final.jar:6.1.5.Final] at
org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:172)
~[hibernate-validator-6.1.5.Final.jar:6.1.5.Final] at
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:116)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:80)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.action.internal.EntityInsertAction.preInsert(EntityInsertAction.java:227)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:100)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:723)
~[na:na] at
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:348)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1360)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:451)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3210)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2378)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] at
org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final] ... 22 common frames
omitted Caused by: java.lang.NullPointerException: null at
com.Alex.Validations.EmailValidator.isValid(EmailValidator.java:26)
~[classes/:na] at
com.Alex.Validations.EmailValidator.isValid(EmailValidator.java:1)
~[classes/:na] at
org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint(ConstraintTree.java:180)
~[hibernate-validator-6.1.5.Final.jar:6.1.5.Final]
UserService class
#Service
public class UserService {
#Autowired
private UserRepository userRep;
public void addUser(User user) {
userRep.save(user);
}
public void deleteUser(long userId) {
userRep.deleteById(userId);
}
public List<User> retrieveAllUsers(){
Iterable<User>temp =userRep.findAll();
List<User>allUsers = null;
temp.forEach(allUsers::add);
return allUsers;
}
public boolean searchByEmail(String email) {
return userRep.findByEmail(email);
}
public void updateUser(User user) {
userRep.save(user);
}
}
Annotation interface class
#Target(ElementType.FIELD)
//When will the annotation be processed compilation, runtime etc
#Retention(RetentionPolicy.RUNTIME)
//Where is the logic
#Constraint(validatedBy = EmailValidator.class)
#Documented
public #interface ValidEmail {
//Error message
String message() default "Invalid email";
//Required for annotation
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Annotation logic class
public class EmailValidator implements ConstraintValidator<ValidEmail, String> {
#Autowired
private UserService service;
//Actual place to place the logic to check if the data is valid or not
#Override
public boolean isValid(String email, ConstraintValidatorContext context) {
if (email == null) {
return false;
}
List<User> users = service.retrieveAllUsers();
if (users.size() > 0) {
return Pattern.matches("(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")#(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])", email)
&& service.searchByEmail(email);
}
else {
return Pattern.matches("(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")#(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])", email);
}
}
#Override
public void initialize(ValidEmail validEmail) {
validEmail.message();
}
}
Main
#SpringBootApplication
#ComponentScan(basePackages = {
"com.Alex.Mains", "com.Alex.UserPackage", "com.Alex.Flights", "com.Alex.Security"
})
#EntityScan( basePackages = {"com.Alex.UserPackage", "com.Alex.Flights"})
#EnableJpaRepositories({"com.Alex.UserPackage", "com.Alex.Flights"})
public class JpaApplication {
public static void main(String[] args) {
SpringApplication.run(JpaApplication.class, args);
}
// #Bean
// public Validator validator(final AutowireCapableBeanFactory beanFactory) {
//
// ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
// .configure()
// .constraintValidatorFactory(new SpringConstraintValidatorFactory(beanFactory))
// .buildValidatorFactory();
//
// return validatorFactory.getValidator();
// }
}
Hibernate is calling the validation and it does not know anything about Spring by default so that #Autowired stereotype is not going to be honoured.
If you want to use Spring there, you need to configure Hibernate to be able to resolve the dependency injection properly.
I can't know for sure as you haven't shared a sample we can run but try to add the following configuration:
#Configuration
class HibernateCustomization {
#Bean
public HibernatePropertiesCustomizer hibernatePropertiesCustomizer(ValidatorFactory validatorFactory) {
return (properties) -> {
properties.put(org.hibernate.cfg.AvailableSettings.JPA_VALIDATION_FACTORY, validatorFactory);
};
}
}