0
votes

I try to read ExcelFiles and save the data in a postgres database. In some files I get the following error message:

java.lang.NullPointerException: null at de.hspf.lectureservice.semesterLecture.SemesterLecture.hashCode(SemesterLecture.java:51) ~[classes/:na] at java.lang.Object.toString(Object.java:236) ~[na:1.8.0_161] at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_161] at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_161] at org.hibernate.pretty.MessageHelper.infoString(MessageHelper.java:57) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.NonUniqueObjectException.getMessage(NonUniqueObjectException.java:61) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:123) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:933) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:892) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.engine.spi.CascadingActions$6.cascade(CascadingActions.java:261) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:490) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:415) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:216) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:523) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:455) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:418) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:216) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:149) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.event.internal.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:460) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.event.internal.DefaultMergeEventListener.entityIsPersistent(DefaultMergeEventListener.java:202) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:176) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:69) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:900) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:886) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final] at sun.reflect.GeneratedMethodAccessor88.invoke(Unknown Source) ~[na:na] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161] at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:308) ~[spring-orm-5.1.6.RELEASE.jar:5.1.6.RELEASE] at com.sun.proxy.$Proxy116.merge(Unknown Source) ~[na:na] at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:492) ~[spring-data-jpa-2.1.6.RELEASE.jar:2.1.6.RELEASE] at sun.reflect.GeneratedMethodAccessor86.invoke(Unknown Source) ~[na:na] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161] at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:359) ~[spring-data-commons-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200) ~[spring-data-commons-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:644) ~[spring-data-commons-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:608) ~[spring-data-commons-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$invoke$3(RepositoryFactorySupport.java:595) ~[spring-data-commons-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:595) ~[spring-data-commons-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:138) ~[spring-data-jpa-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.1.6.RELEASE.jar:2.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at com.sun.proxy.$Proxy126.save(Unknown Source) ~[na:na] at de.hspf.lectureservice.lecture.LectureService.readExcelFile(LectureService.java:111) ~[classes/:na] at de.hspf.lectureservice.lecture.LectureService.readExcelFileFolder(LectureService.java:56) ~[classes/:na] at de.hspf.lectureservice.lecture.LectureService$$FastClassBySpringCGLIB$$c90e79de.invoke() ~[classes/:na] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] at de.hspf.lectureservice.lecture.LectureService$$EnhancerBySpringCGLIB$$8c87ac4c.readExcelFileFolder() ~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161] at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:261) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:179) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:142) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.boot.context.event.EventPublishingRunListener.running(EventPublishingRunListener.java:105) ~[spring-boot-2.1.4.RELEASE.jar:2.1.4.RELEASE] at org.springframework.boot.SpringApplicationRunListeners.running(SpringApplicationRunListeners.java:78) ~[spring-boot-2.1.4.RELEASE.jar:2.1.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:332) [spring-boot-2.1.4.RELEASE.jar:2.1.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.4.RELEASE.jar:2.1.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.4.RELEASE.jar:2.1.4.RELEASE] at de.hspf.lectureservice.LectureServiceApplication.main(LectureServiceApplication.java:15) [classes/:na]

@Entity
public class SemesterLecture implements Serializable {
    @Id
    @ManyToOne
    @JsonIgnore
    @JoinColumn
    private Semester semester;

    @Id
    @ManyToOne
    @JoinColumn
    private Lecture lecture;

    private String grade;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    private List<LectureDateTime> lectureDateTimes;

    public SemesterLecture(Lecture lecture, String grade) {
        this.lecture = lecture;
        this.grade = grade;
    }

    public SemesterLecture() {
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof SemesterLecture)) return false;
        SemesterLecture that = (SemesterLecture) o;
        return Objects.equals(semester.getTitle(), that.semester.getTitle()) &&
                Objects.equals(lecture.getTitle(), that.lecture.getTitle());
    }

@Override
    public int hashCode() {
        return Objects.hash(semester.getTitle(), lecture.getTitle(), grade);
    }
@EventListener(ApplicationReadyEvent.class)
    @Transactional
    public void readExcelFileFolder() throws IOException, InvalidFormatException, NotFoundException {
        LOG.info("Load Excel Files from folder...");
        FileFilter filter = new ExcelFileFilter ();
        Resource[] resourceFiles = resourcePatternResolver.getResources("classpath:excel-files/*.xls");
        for (Resource resource : resourceFiles) {
            readExcelFile(resource.getInputStream(), resource.getFilename());
        }
    }

    public void readExcelFile(InputStream inputStream, String fileName) throws IOException, InvalidFormatException, NotFoundException {
        Workbook workbook = WorkbookFactory.create(inputStream);
        DataFormatter dataFormatter = new DataFormatter();
        LOG.info("Read Excel File: " + fileName.substring(0, fileName.lastIndexOf('.')));

        Course existingCourse = courseRepository.findByCourseNumber(fileName.replace(" ", "").substring(0, fileName.lastIndexOf('.')));
        if(existingCourse == null){
            return;
        }
        LOG.info("Found course with title " + existingCourse.getCourseTitle());

        if(existingCourse.getSemesters().size() < 1){
            for(int i = 1; i < 8; i++){
                Semester semester = new Semester();
                semester.setTitle("Semester " + i);
                semester.setSemesterLectures(new ArrayList<SemesterLecture>());
                semester.setSemesterNumber(i);
                existingCourse.getSemesters().add(semesterRepository.save(semester));
            }
            LOG.info("Added " + existingCourse.getSemesters().size() + " Semesters");
        }

        for(int y = 0; y < 5; y++){
            Sheet sheet = workbook.getSheetAt(y);
            for (Row row: sheet) {
                String title = dataFormatter.formatCellValue(row.getCell(0));
                String modulNumber = dataFormatter.formatCellValue(row.getCell(1)).replace(" ", "");
                String language = dataFormatter.formatCellValue(row.getCell(2));
                int semesterNumber = 1;
                try{
                    semesterNumber = Integer.parseInt(dataFormatter.formatCellValue(row.getCell(3)).replace(".", ""));
                }catch (Exception e){}
                if(title instanceof String && modulNumber instanceof String && !title.isEmpty() && !modulNumber.isEmpty() && !title.startsWith("Module")){
                    try{
                        if(lectureRepository.existsByModulNumber(modulNumber.replace(" ", ""))){
                            Lecture lecture = lectureRepository.findByModulNumber(modulNumber.replace(" ", ""));
                            SemesterLecture sm = new SemesterLecture(lecture, "0");
                            sm.setSemester(existingCourse.getSemesters().get(semesterNumber-1));
                            sm.setLecture(lecture);
                            sm.setGrade("0");
                            existingCourse.getSemesters().get(semesterNumber-1).getSemesterLectures().add(sm);
                            LOG.info(sm.getLecture().getTitle() + sm.getSemester().getTitle());
                        }
                    } catch (NumberFormatException e) {
                        throw new NotFoundException("Lecture does not exist");
                    }
                }
            }
        }

        for(Semester semester : existingCourse.getSemesters()){
            semesterRepository.save(semester);
        }
        courseRepository.save(existingCourse);
        LOG.info("Saved all lectures from course " + existingCourse.getCourseTitle());
    }

In most of the crawled data nothing is happening. The error appears when I try to save the semster object. The Excel file has the following structure: title, modulnumber, language, semesterNumber

1
what is in your hashcode method?zlaval
@Override public int hashCode() { return Objects.hash(semester.getTitle(), lecture.getTitle(), grade); }softwareUser
use debugger, one of those values in Objects.hash is null. hash make a nullpoint check on parameter, but if semester or lecture are null, it will throw nullpointer on getterszlaval
So you think that in one semesterlecture there is a lecture or semester with null? Because when I debug the course where the error occurs everyhting looks fine...softwareUser
it is a maybe, i just think that from stacktracezlaval

1 Answers

1
votes

Folloowing the stack trace, I think you have two problems :

  • The first one, which is hidden by the second one, is that you're trying to save a SemesterLecture Instance which have the same primary id (ie. the same value for the couple SemesterLecture) that a one which already exists in database, hence the NonUniqueObjectException which can be seen in your stack trace
  • The second one is that Spring, when trying to print the message of the NonUniqueObjectException, end by calling the hash method of your SemesterLecture class, for an instance which have the field semester or the field lecture set to null, hence the NullPointerException in fine.

My suggestion :

First, remove or comment the hash method for the SemesterLecture class. The default one is enough for a start, and it will allow you to see your original exception. My guess is that there is a bug in your Semester or your Lecture class hash or equals method, leading hibernate to mistake two entity as the same one.