Skip to content

Comments

Refactor Job and Report persistence to use JPA for active states and flush to storage on completion#3597

Draft
Copilot wants to merge 9 commits intodevelopmentfrom
copilot/refactor-job-report-persistence
Draft

Refactor Job and Report persistence to use JPA for active states and flush to storage on completion#3597
Copilot wants to merge 9 commits intodevelopmentfrom
copilot/refactor-job-report-persistence

Conversation

Copy link
Contributor

Copilot AI commented Feb 20, 2026

  • Previous implementation: JPA converters, entity annotations, repositories, DefaultModelService refactoring

Requested Changes:

  • Job stats in separate columns: Expanded JobStats fields into individual columns in the jobs table
  • Create StepReport entity: Created new StepReport JPA entity with proper foreign key relationship
  • Fix line separator: Updated addReport() to avoid repeated newlines
  • Fix NullPointerException: Initialize jobStats field with new JobStats() instead of null to avoid NPE when code accesses jobStats directly

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Refactor Job and Report persistence to use relational database Refactor Job and Report persistence to use JPA for active states and flush to storage on completion Feb 20, 2026
Copilot AI requested a review from hmiguim February 20, 2026 09:29
@luis100
Copy link
Member

luis100 commented Feb 20, 2026

@copilot I've updated the firewall rules so you can access the sites you wanted.

@luis100 luis100 self-requested a review February 20, 2026 09:46
@hmiguim
Copy link
Member

hmiguim commented Feb 20, 2026

@copilot I've updated the firewall rules so you can access the sites you wanted.

@hmiguim
Copy link
Member

hmiguim commented Feb 20, 2026

@copilot
I run this command: mvn -pl roda-ui/roda-wui -am spring-boot:run -Pdebug-main

And got this:

[12:48 PM]Feb 20, 2026 12:47:44 PM org.apache.coyote.AbstractProtocol init INFO: Initializing ProtocolHandler ["http-nio-8080"] Feb 20, 2026 12:47:44 PM org.apache.catalina.core.StandardService startInternal INFO: Starting service [Tomcat] Feb 20, 2026 12:47:44 PM org.apache.catalina.core.StandardEngine startInternal INFO: Starting Servlet engine: [Apache Tomcat/10.1.46] Feb 20, 2026 12:47:44 PM org.apache.catalina.core.ApplicationContext log INFO: Initializing Spring embedded WebApplicationContext Feb 20, 2026 12:47:46 PM org.apache.catalina.core.StandardService stopInternal INFO: Stopping service [Tomcat]

Why is spring not starting?

@hmiguim
Copy link
Member

hmiguim commented Feb 20, 2026

@copilot

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2026-02-20T13:17:10.574Z ERROR 1696212 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reportRepository' defined in org.roda.core.repository.job.ReportRepository defined in @EnableJpaRepositories declared on RODA: Not a managed type: class org.roda.core.data.v2.jobs.Report
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1826) ~[spring-beans-6.2.11.jar:6.2.11]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:607) ~[spring-beans-6.2.11.jar:6.2.11]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:529) ~[spring-beans-6.2.11.jar:6.2.11]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:339) ~[spring-beans-6.2.11.jar:6.2.11]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:373) ~[spring-beans-6.2.11.jar:6.2.11]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:337) ~[spring-beans-6.2.11.jar:6.2.11]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-6.2.11.jar:6.2.11]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.instantiateSingleton(DefaultListableBeanFactory.java:1215) ~[spring-beans-6.2.11.jar:6.2.11]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingleton(DefaultListableBeanFactory.java:1187) ~[spring-beans-6.2.11.jar:6.2.11]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:1123) ~[spring-beans-6.2.11.jar:6.2.11]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:987) ~[spring-context-6.2.11.jar:6.2.11]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:627) ~[spring-context-6.2.11.jar:6.2.11]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.4.10.jar:3.4.10]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) ~[spring-boot-3.4.10.jar:3.4.10]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[spring-boot-3.4.10.jar:3.4.10]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) ~[spring-boot-3.4.10.jar:3.4.10]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) ~[spring-boot-3.4.10.jar:3.4.10]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) ~[spring-boot-3.4.10.jar:3.4.10]
at org.roda.wui.RODA.main(RODA.java:32) ~[classes/:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.4.10.jar:3.4.10]
Caused by: java.lang.IllegalArgumentException: Not a managed type: class org.roda.core.data.v2.jobs.Report
at org.hibernate.metamodel.model.domain.internal.JpaMetamodelImpl.managedType(JpaMetamodelImpl.java:223) ~[hibernate-core-6.6.29.Final.jar:6.6.29.Final]
at org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl.managedType(MappingMetamodelImpl.java:470) ~[hibernate-core-6.6.29.Final.jar:6.6.29.Final]
at org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl.managedType(MappingMetamodelImpl.java:100) ~[hibernate-core-6.6.29.Final.jar:6.6.29.Final]
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.(JpaMetamodelEntityInformation.java:82) ~[spring-data-jpa-3.4.10.jar:3.4.10]
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:69) ~[spring-data-jpa-3.4.10.jar:3.4.10]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:251) ~[spring-data-jpa-3.4.10.jar:3.4.10]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:215) ~[spring-data-jpa-3.4.10.jar:3.4.10]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:198) ~[spring-data-jpa-3.4.10.jar:3.4.10]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:1) ~[spring-data-jpa-3.4.10.jar:3.4.10]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:377) ~[spring-data-commons-3.4.10.jar:3.4.10]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$4(RepositoryFactoryBeanSupport.java:350) ~[spring-data-commons-3.4.10.jar:3.4.10]
at org.springframework.data.util.Lazy.getNullable(Lazy.java:135) ~[spring-data-commons-3.4.10.jar:3.4.10]
at org.springframework.data.util.Lazy.get(Lazy.java:113) ~[spring-data-commons-3.4.10.jar:3.4.10]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:356) ~[spring-data-commons-3.4.10.jar:3.4.10]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:132) ~[spring-data-jpa-3.4.10.jar:3.4.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1873) ~[spring-beans-6.2.11.jar:6.2.11]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1822) ~[spring-beans-6.2.11.jar:6.2.11]
... 21 common frames omitted

Copy link
Contributor Author

Copilot AI commented Feb 20, 2026

@copilot
I run this command: mvn -pl roda-ui/roda-wui -am spring-boot:run -Pdebug-main

...

Spring was failing to start because the @EntityScan in RODA.java wasn't including the org.roda.core.data.v2.jobs package where the Job and Report entities are located. This caused the "Not a managed type" error you saw in your follow-up comment. I fixed this in commit 09dd022 by updating the @EntityScan annotation to include both packages. Please pull the latest changes and try again.

@copilot

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
...

Fixed in commit 09dd022. The @EntityScan in RODA.java was only scanning org.roda.core.entity, but the Job and Report entities are in org.roda.core.data.v2.jobs. I've updated it to:

@EntityScan(basePackages = {"org.roda.core.entity", "org.roda.core.data.v2.jobs"})

Please pull the latest changes and run again.

Copy link
Member

@luis100 luis100 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Job stats should be in separated columns.
  • Reports inside of the Report should have a different class name, such as StepReport, to discern job reports from step reports that are in a job report. They should also be a separated JPA entity and not put all together in a single column.
  • When looking at the content, line separator seems to be repeated (many \n instead of just one).

@luis100 luis100 removed the request for review from hmiguim February 20, 2026 17:01
@hmiguim hmiguim marked this pull request as ready for review February 20, 2026 17:03
@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Feb 20, 2026
@hmiguim
Copy link
Member

hmiguim commented Feb 20, 2026

Review:

  • Job stats should be in separated columns.
  • Reports inside of the Report should have a different class name, such as StepReport, to discern job reports from step reports that are in a job report. They should also be a separated JPA entity and not put all together in a single column.
  • When looking at the content, line separator seems to be repeated (many \n instead of just one).

@dosubot dosubot bot added the enhancement label Feb 20, 2026
@hmiguim hmiguim requested a review from luis100 February 20, 2026 17:05
@hmiguim
Copy link
Member

hmiguim commented Feb 20, 2026

@copilot check the requested changes

@dosubot
Copy link

dosubot bot commented Feb 20, 2026

Related Documentation

Checked 5 published document(s) in 1 knowledge base(s). No updates required.

How did I do? Any feedback?  Join Discord

Copilot AI and others added 2 commits February 20, 2026 17:09
…ries, and refactor DefaultModelService for hybrid persistence

Co-authored-by: hmiguim <1252710+hmiguim@users.noreply.github.com>
Copilot AI and others added 4 commits February 20, 2026 17:09
…t entity scanning

Co-authored-by: hmiguim <1252710+hmiguim@users.noreply.github.com>
…edundant calls

Co-authored-by: hmiguim <1252710+hmiguim@users.noreply.github.com>
Co-authored-by: hmiguim <1252710+hmiguim@users.noreply.github.com>
@luis100 luis100 force-pushed the copilot/refactor-job-report-persistence branch from 09dd022 to 677fa76 Compare February 20, 2026 17:10
Copilot AI and others added 2 commits February 20, 2026 17:11
… line separator

Co-authored-by: hmiguim <1252710+hmiguim@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 20, 2026

@copilot check the requested changes

Implemented in commit 1085230:

  1. Job stats in separate columns: JobStats fields are now stored as 9 individual columns (stats_completion_percentage, stats_source_objects_count, etc.) instead of a JSON TEXT column.

  2. StepReport entity: Created new StepReport JPA entity with its own table (job_step_reports) and foreign key (parent_report_id). The Report.reports field now uses @OneToMany relationship with cascade operations instead of JSON serialization.

  3. Line separator fix: Updated addReport() to use a single \n as default separator when lineSeparator is empty, avoiding repeated newlines.

Copilot AI requested a review from hmiguim February 20, 2026 17:13
@luis100 luis100 changed the base branch from master to development February 20, 2026 17:15
@luis100 luis100 marked this pull request as draft February 20, 2026 17:32
@hmiguim
Copy link
Member

hmiguim commented Feb 20, 2026

@copilot

I got some errors:

2026-02-20 17:30:04,112 [http-nio-8080-exec-1] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Re
quest processing failed: java.lang.NullPointerException: Cannot invoke "org.roda.core.data.v2.jobs.JobStats.setSourceObjectsCount(int)" because "this.jobStats" is null] with root cause
java.lang.NullPointerException: Cannot invoke "org.roda.core.data.v2.jobs.JobStats.setSourceObjectsCount(int)" because "this.jobStats" is null
        at org.roda.core.data.v2.jobs.Job.(Job.java:177)
        at org.roda.wui.api.v2.services.JobService.createJob(JobService.java:105)
        at org.roda.wui.api.v2.controller.JobsController.createJob(JobsController.java:145)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)

…() instead of null

Co-authored-by: hmiguim <1252710+hmiguim@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 20, 2026

@copilot

I got some errors:
...

Fixed in commit 1708cfc. The jobStats field was initialized as null instead of new JobStats(). This caused a NullPointerException when code accessed jobStats directly (e.g., in the copy constructor). I've updated the initialization to private JobStats jobStats = new JobStats(); and changed direct field access to use getJobStats() instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants