-
Notifications
You must be signed in to change notification settings - Fork 1
[BI-2110] New Append Exp Validations #483
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
nickpalladino
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a few questions about things I saw when testing.
If the "Sub Obs Unit" ObsUnitID was invalid (missing or not a UUID) I was getting an error banner with An unknown error has occurred when processing your import. I was expecting a more descriptive message, like something about the UUID being invalid. Here's the stack trace:
2025-08-19 15:39:02.094-0400 [ForkJoinPool.commonPool-worker-3] ERROR o.b.b.i.services.FileImportService - null
java.lang.NullPointerException: null
at org.breedinginsight.brapps.importer.services.processors.experiment.appendoverwrite.factory.entity.PendingStudy.brapiRead(PendingStudy.java:78)
at org.breedinginsight.brapps.importer.services.processors.experiment.appendoverwrite.factory.action.WorkflowReadInitialization.execute(WorkflowReadInitialization.java:51)
at org.breedinginsight.brapps.importer.services.processors.experiment.appendoverwrite.middleware.initialize.WorkflowInitialization.process(WorkflowInitialization.java:59)
at org.breedinginsight.brapps.importer.services.processors.experiment.appendoverwrite.middleware.initialize.WorkflowInitialization.process(WorkflowInitialization.java:39)
at org.breedinginsight.brapps.importer.services.processors.experiment.appendoverwrite.AppendOverwritePhenotypesWorkflow.process(AppendOverwritePhenotypesWorkflow.java:127)
at org.breedinginsight.brapps.importer.services.processors.experiment.ExperimentWorkflowNavigator.lambda$process$0(ExperimentWorkflowNavigator.java:60)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1599)
at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:543)
at org.breedinginsight.brapps.importer.services.processors.experiment.ExperimentWorkflowNavigator.process(ExperimentWorkflowNavigator.java:63)
at org.breedinginsight.brapps.importer.model.imports.DomainImportService.process(DomainImportService.java:59)
at org.breedinginsight.brapps.importer.services.FileImportService.lambda$processFile$8(FileImportService.java:423)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1771)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1763)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1016)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1665)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1598)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
When adding a new Sub Obs Unit variable and appending new observation values the front-end (feature/BI-2628-2) shows 2 for observation variables in the header (think it should be 1 unless it's including the Exp Unit level variable as well?) and doesn't show the table. The api response for GET /v1/programs/8051df4f-d40f-43c9-8fc0-f6500eefebb0/import/mappings/c3a921ad-f35e-402c-b1f2-4678810c14d3/data/41d4401a-95f0-4ee3-96a2-7e918c581351?mapping=true has "Sub Unit ID" as one of the entries in the dynamicColumnNames array. I'm guessing that's because we don't have "Sub Unit ID" in the database import mapping. I was also seeing some stuff in the console:
[Vue warn]: Error in render: "TypeError: can't access property "state", row.data.observations[this.observationIndexMap.get(...)] is undefined"
found in
---> <BTable> at src/views/PageNotFound.vue
<ExpandableTable> at src/components/tables/expandableTable/ExpandableTable.vue
<ImportTemplate> at src/views/import/ImportTemplate.vue
<ImportExperiment> at src/views/import/ImportExperiment.vue
<ImportFile> at src/views/import/ImportFile.vue
<SideBarMaster> at src/components/layouts/BaseSideBarLayout.vue
<UserSideBarLayout> at src/components/layouts/UserSideBarLayout.vue
<App> at src/App.vue
<Root> vue.runtime.esm.js:4662:21
TypeError: can't access property "state", row.data.observations[this.observationIndexMap.get(...)] is undefined
cellClassIfExisting webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportExperiment.vue?vue&type=script&lang=ts&:256
getRootClasses webpack-internal:///./node_modules/buefy/dist/esm/table.js:272
2 webpack-internal:///./node_modules/buefy/dist/esm/table.js:1551
renderList VueJS
2 webpack-internal:///./node_modules/buefy/dist/esm/table.js:1551
renderList VueJS
__vue_render__$2 webpack-internal:///./node_modules/buefy/dist/esm/table.js:1548
VueJS 13
statisticsLoaded webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportExperiment.vue?vue&type=script&lang=ts&:228
VueJS 4
_callee8$ webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=script&lang=ts&:697
f webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
A webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
n webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
Babel 6
getDataUpload webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=script&lang=ts&:731
_callee8$ webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=script&lang=ts&:679
f webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
A webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
n webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
Babel 8
getDataUpload webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=script&lang=ts&:731
_callee7$ webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=script&lang=ts&:626
f webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
A webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
n webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
Babel 6
updateDataUpload webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=script&lang=ts&:637
_callee2$ webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=script&lang=ts&:283
f webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
A webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
n webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
Babel 6
upload webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=script&lang=ts&:338
actions webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=script&lang=ts&:184
s webpack-internal:///./node_modules/@xstate/fsm/es/index.js:20
vue.runtime.esm.js:3104:17
[Vue warn]: Error in render: "TypeError: can't access property "state", row.data.observations[this.observationIndexMap.get(...)] is undefined"
found in
---> <BTable> at src/views/PageNotFound.vue
<ExpandableTable> at src/components/tables/expandableTable/ExpandableTable.vue
<ImportTemplate> at src/views/import/ImportTemplate.vue
<ImportExperiment> at src/views/import/ImportExperiment.vue
<ImportFile> at src/views/import/ImportFile.vue
<SideBarMaster> at src/components/layouts/BaseSideBarLayout.vue
<UserSideBarLayout> at src/components/layouts/UserSideBarLayout.vue
<App> at src/App.vue
<Root> vue.runtime.esm.js:4662:21
TypeError: can't access property "state", row.data.observations[this.observationIndexMap.get(...)] is undefined
cellClassIfExisting webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportExperiment.vue?vue&type=script&lang=ts&:256
getRootClasses webpack-internal:///./node_modules/buefy/dist/esm/table.js:272
2 webpack-internal:///./node_modules/buefy/dist/esm/table.js:1551
renderList VueJS
2 webpack-internal:///./node_modules/buefy/dist/esm/table.js:1551
renderList VueJS
__vue_render__$2 webpack-internal:///./node_modules/buefy/dist/esm/table.js:1548
VueJS 14
_callee2$ webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=script&lang=ts&:303
f webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
A webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
n webpack-internal:///./node_modules/vue-breakpoint-component/dist/vue-breakpoint-component.umd.min.js:9
Babel 8
upload webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=script&lang=ts&:338
actions webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=script&lang=ts&:184
s webpack-internal:///./node_modules/@xstate/fsm/es/index.js:20
s webpack-internal:///./node_modules/@xstate/fsm/es/index.js:20
send webpack-internal:///./node_modules/@xstate/fsm/es/index.js:20
import webpack-internal:///./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"69a64f48-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/import/ImportTemplate.vue?vue&type=template&id=755668df&:147
VueJS 4
click webpack-internal:///./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"69a64f48-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/file-import/FileSelectMessageBox.vue?vue&type=template&id=42958905&:62
VueJS 33
vue.runtime.esm.js:3104:17
|
Current status: Added:
Still TODO:
|
| // Extract the environment and experimental unit ID and germplasm GID from the ExperimentObservation object | ||
| // and pass them to the createObservationUnitKey method | ||
| return createObservationUnitKey(importRow.getEnv(), importRow.getExpUnitId()); | ||
| return createObservationUnitKey(importRow.getEnv(), importRow.getExpUnitId(), importRow.getGid()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't env, exp unit id, and gid all be the same for the sub entity case? If there were 5 repeats, ex:
env, exp unit id, gid
CA, 1, 1
CA, 1, 1
CA, 1, 1
CA, 1, 1
CA, 1, 1
We will have sub unit id available once it's added to the download file that would uniquely identify each row.
Description
Story: BI-2110
Summarize these file changes made for a pull request:
This pull request introduces several major improvements and fixes related primarily to enhancing validation and import workflow handling for appending and overwriting experimental data, particularly around observation variables and observation units for datasets. Here's a summary of the key changes:
AppendOverwriteVariableValidation).DynamicObsUnitValidator(replacingDynamicColumnValidatorfor observation units).ObservationUnitSingleDatasetValidatorthat ensures observation units used in the import belong to a single dataset (prevents mixing units from multiple datasets in one import).DynamicObsVarValidatorfor observation variable validators.ObservationVariablePriorDatasetValidator).ObservationVariableTimestampValidator).ObservationVariableValidatorthat chains multiple dynamic observation variable validators.PendingDatasetto fetch datasets by IDs and support more robust dataset retrieval with associated program scoping.Overall, this PR significantly strengthens validation logic for experiment data import workflows, ensuring observation units and variables are properly validated for duplication, formatting, dataset association, and timestamp matching. It also improves test coverage for these scenarios and refines core import processing to handle them correctly.
Dependencies
biweb:develop
Note: you can optionally use the fix in biweb:feature/BI-2628-2 to display the correct number of obs var columns in the preview import statistics.
Testing
Setup
Prior Observation Variable Validation
Single Dataset Validation
Checklist: