0

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

10
  • what is in your hashcode method? Commented Jul 14, 2019 at 19:20
  • @Override public int hashCode() { return Objects.hash(semester.getTitle(), lecture.getTitle(), grade); } Commented Jul 14, 2019 at 19:21
  • 2
    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 getters Commented Jul 14, 2019 at 19:25
  • 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... Commented Jul 14, 2019 at 19:33
  • it is a maybe, i just think that from stacktrace Commented Jul 14, 2019 at 19:35

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

You are right. After commenting the hash mehtod I get the following error: org.springframework.dao.DataIntegrityViolationException: A different object with the same identifier value was already associated with the session. Do you have an idea how I can solve that? When I try to add an autogenerated id spring should recognize the different objects, right?
@softwareUser Adding an autogenerated id should do the trick. Using business value as a primary key is generally considered a bad practice. But without more information, I cannot give you a perfect answer. You will have to try and learn :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.