Skip to content
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

Global: Update internal storage and add CRUD operations #246

Merged

Conversation

GeoffreyKarnbach
Copy link
Contributor

Description

Feature:

What does this PR do?

Added active boolean to internal Storage Entities. Added CRUD for Internal Storage and Internal Storage Translations.
The validator of the backend for dmp, where the activeness status of the Internal Storages is disabled (bug, needs to be adressed).

Breaking changes

Rework of the InternalStorageDO, changes are reflected in the frontend as well.

Code review focus

Dependencies

Checks

  • Tested with Oracle/PostgreSQL
  • Export updated
  • Documentation added
  • Tests added
  • E2e tests created
  • Successfully ran e2e tests before merge

closes GH-198
closes GH-95

Copy link
Collaborator

@rekt-hard rekt-hard left a comment

Choose a reason for hiding this comment

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

Massive work - thank you for digging into this and also coming up with a first approach for the search.

Search
This shows how we can be very explicit about the search yet the modularity is missing. If this were to applied to another resource/service/repo, all the logic would have to be duplicated. I have created an issue detailing the general approach: #249

Validation
We can perform object validation on the service level: https://quarkus.io/guides/validation#service-method-validation. *DO objects used in the application are the ones for the API. Constraints can be defined on these classes and then be validated in the service.

Exceptions
We do not have to re-throw most exceptions on the resource level. If the service level throws, the resource will propagate it to the client. A client also has enough context to know on which request this happened (e.g. it knows that it tried to update a DMP and something went wrong).

Common error response
In order to easily show errors and warnings in the front end, we should come up with a common error interface. There is an extra issue for this now: #250

@GeoffreyKarnbach GeoffreyKarnbach force-pushed the gk/95-allow-internal-storages-to-be-disabled-for-the-frontend branch 3 times, most recently from c1920d7 to 3819192 Compare September 3, 2024 13:24
@GeoffreyKarnbach GeoffreyKarnbach force-pushed the gk/95-allow-internal-storages-to-be-disabled-for-the-frontend branch 8 times, most recently from b9d3bba to 870b5ee Compare September 10, 2024 12:55
Copy link
Collaborator

@rekt-hard rekt-hard left a comment

Choose a reason for hiding this comment

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

Massive work - thank you!

Exception Handling

We have a separate issue for this so will try to keep it short.
What would be desired is to remove the exception handling from the resource level. There should be a possibility to register a handler for certain exception types, which then takes care of generating an appropriate response. If an exception is raised on the service level, this should get propagated to the resource level and the application wide handlers kick in.

Storage Resource

Resources for storage and storage translations can be merged, as they are tightly coupled. See comments for more details.

Entity Deletion

We should think about if we want to soft delete by default. This way, accidental deletions can be restored easily. For removing an entity completely, a purge method could be introduced.

@GeoffreyKarnbach GeoffreyKarnbach force-pushed the gk/95-allow-internal-storages-to-be-disabled-for-the-frontend branch from 641aaae to 2ba2540 Compare October 1, 2024 09:34
Copy link
Collaborator

@rekt-hard rekt-hard left a comment

Choose a reason for hiding this comment

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

Generally looking good. Some comments that should be rather quick to address.

One major issue:
I am getting an error on the admin page when fetching the internal storage.

HTTP Request to /api/storages failed, error id: e7ed2b7f-73ad-4422-8192-d2b31b219114-12: org.hibernate.PropertyAccessException: Null value was assigned to a property [class org.damap.base.domain.InternalStorage.active] of primitive type: 'org.damap.base.domain.InternalStorage.active' (setter)
	at org.hibernate.property.access.spi.SetterFieldImpl.set(SetterFieldImpl.java:63)
	at org.hibernate.property.access.spi.EnhancedSetterImpl.set(EnhancedSetterImpl.java:42)
	at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:4459)
	at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.initializeEntityInstance(AbstractEntityInitializer.java:809)
	at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.initializeEntity(AbstractEntityInitializer.java:769)
	at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.initializeInstance(AbstractEntityInitializer.java:761)
	at org.hibernate.sql.results.internal.InitializersList.initializeInstance(InitializersList.java:73)
	at org.hibernate.sql.results.internal.StandardRowReader.coordinateInitializers(StandardRowReader.java:113)
	at org.hibernate.sql.results.internal.StandardRowReader.readRow(StandardRowReader.java:87)
	at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:205)
	at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:33)
	at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.doExecuteQuery(JdbcSelectExecutorStandardImpl.java:211)
	at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.executeQuery(JdbcSelectExecutorStandardImpl.java:83)
	at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:76)
	at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:65)
	at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.lambda$new$2(ConcreteSqmSelectQueryPlan.java:139)
	at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.withCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:382)
	at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:302)
	at org.hibernate.query.sqm.internal.QuerySqmImpl.doList(QuerySqmImpl.java:526)
	at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:423)
	at org.hibernate.query.Query.getResultList(Query.java:120)
	at io.quarkus.hibernate.orm.panache.common.runtime.CommonPanacheQueryImpl.list(CommonPanacheQueryImpl.java:312)
	at io.quarkus.hibernate.orm.panache.runtime.PanacheQueryImpl.list(PanacheQueryImpl.java:149)
	at io.quarkus.hibernate.orm.panache.runtime.JpaOperations.list(JpaOperations.java:24)
	at io.quarkus.hibernate.orm.panache.runtime.JpaOperations.list(JpaOperations.java:10)
	at io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations.list(AbstractJpaOperations.java:253)
	at org.damap.base.repo.InternalStorageRepo.list(InternalStorageRepo.java)
	at org.damap.base.repo.base.RepoSearch.searchByParameters(RepoSearch.java:56)
	at org.damap.base.repo.InternalStorageRepo_ClientProxy.searchByParameters(Unknown Source)
	at org.damap.base.rest.storage.InternalStorageService.search(InternalStorageService.java:180)
	at org.damap.base.rest.storage.InternalStorageService_ClientProxy.search(Unknown Source)
	at org.damap.base.rest.InternalStorageResource.search(InternalStorageResource.java:132)
	at org.damap.base.rest.InternalStorageResource_Subclass.search$$superforward(Unknown Source)
	at org.damap.base.rest.InternalStorageResource_Subclass$$function$$11.apply(Unknown Source)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:73)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext$NextAroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:97)
	at io.quarkus.security.runtime.interceptor.SecurityHandler.handle(SecurityHandler.java:27)
	at io.quarkus.security.runtime.interceptor.AuthenticatedInterceptor.intercept(AuthenticatedInterceptor.java:29)
	at io.quarkus.security.runtime.interceptor.AuthenticatedInterceptor_Bean.intercept(Unknown Source)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:70)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:62)
	at io.quarkus.resteasy.reactive.server.runtime.StandardSecurityCheckInterceptor.intercept(StandardSecurityCheckInterceptor.java:44)
	at io.quarkus.resteasy.reactive.server.runtime.StandardSecurityCheckInterceptor_AuthenticatedInterceptor_Bean.intercept(Unknown Source)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:30)
	at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:27)
	at org.damap.base.rest.InternalStorageResource_Subclass.search(Unknown Source)
	at org.damap.base.rest.InternalStorageResource$quarkusrestinvoker$search_959072baf5d22d5060f26385d4774d1f0c6ee23b.invoke(Unknown Source)
	at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
	at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
	at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:599)
	at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2516)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2495)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1521)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: java.lang.IllegalArgumentException: Can not set boolean field org.damap.base.domain.InternalStorage.active to null value
	at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
	at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
	at java.base/jdk.internal.reflect.UnsafeBooleanFieldAccessorImpl.set(UnsafeBooleanFieldAccessorImpl.java:80)
	at java.base/java.lang.reflect.Field.set(Field.java:799)
	at org.hibernate.property.access.spi.SetterFieldImpl.set(SetterFieldImpl.java:57)

Copy link
Collaborator

@rekt-hard rekt-hard left a comment

Choose a reason for hiding this comment

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

major: ouch. we have a hard dependency on an English translations being present when exporting a document. So when providing only a German translation, the export fails. Could I ask you to update the relevant code and try to fetch the English Translation. If this does not exist, just use the first one available?

internalStorageTranslationRepo
.getInternalStorageById(((Storage) host).getInternalStorageId().id, "eng")
.getDescription();

java.lang.NullPointerException: Cannot invoke "org.damap.base.domain.InternalStorageTranslation.getDescription()" because the return value of "org.damap.base.repo.InternalStorageTranslationRepo.getInternalStorageById(java.lang.Long, String)" is null
	at org.damap.base.conversion.AbstractTemplateExportScienceEuropeComponents.storageInformation(AbstractTemplateExportScienceEuropeComponents.java:411)
	at org.damap.base.conversion.AbstractTemplateExportScienceEuropeComponents.loadScienceEuropeContent(AbstractTemplateExportScienceEuropeComponents.java:38)
	at org.damap.base.conversion.ExportFWFTemplate.exportTemplate(ExportFWFTemplate.java:42)
	at org.damap.base.conversion.ExportFWFTemplate_ClientProxy.exportTemplate(Unknown Source)
	at org.damap.base.conversion.ExportTemplateBroker.exportTemplateByType(ExportTemplateBroker.java:69)
	at org.damap.base.conversion.ExportTemplateBroker_ClientProxy.exportTemplateByType(Unknown Source)
	at org.damap.base.rest.DmpDocumentResource.exportTemplate(DmpDocumentResource.java:56)

@GeoffreyKarnbach GeoffreyKarnbach force-pushed the gk/95-allow-internal-storages-to-be-disabled-for-the-frontend branch from dab8a04 to 6bee717 Compare October 21, 2024 07:59
Copy link
Collaborator

@rekt-hard rekt-hard left a comment

Choose a reason for hiding this comment

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

Thank you for incorporating all the feedback 🚀
Could I ask you to rebase and update the change log file, so it matches the next release version (4.3.0)?

@GeoffreyKarnbach GeoffreyKarnbach force-pushed the gk/95-allow-internal-storages-to-be-disabled-for-the-frontend branch 2 times, most recently from 5bc3cde to 06be7bd Compare October 23, 2024 07:05
@GeoffreyKarnbach GeoffreyKarnbach force-pushed the gk/95-allow-internal-storages-to-be-disabled-for-the-frontend branch from 06be7bd to 3b4b8e0 Compare October 23, 2024 07:06
Copy link

Copy link
Collaborator

@rekt-hard rekt-hard left a comment

Choose a reason for hiding this comment

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

Tested locally with clean database as well as existing database. Good job 👏

@rekt-hard rekt-hard merged commit aa8b435 into next Oct 23, 2024
2 checks passed
@rekt-hard rekt-hard deleted the gk/95-allow-internal-storages-to-be-disabled-for-the-frontend branch October 23, 2024 07:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Expand the InternalStorageService Allow internal storages to be disabled for the frontend
2 participants