Difference between Ebean.update (11) and DB.update (12)

67 views
Skip to first unread message

Loïc Calvez

unread,
Jun 10, 2024, 3:41:17 PM6/10/24
to Ebean ORM

Hi,

I am currently upgrading ebean from version 11.33.2 to 12.16.1, and I am encountering issues with using the DB.update(Object bean) method.

Here is a code example with ebean version 11.33.2 :


    public static void main(String args[]) {

        Demande demande; // come from user input

        Demande originalDemande; // come from database

        // demande and originalDemande have different dateDebut

       

        processDemande(demande, originalDemande);

    }

   

    public void processDemande(Demande originalDemande, Demande demande) {

        boolean hasDateChanged = !besoin.dateDebut.equals(originalBesoin.dateDebut);

        if (hasDateChanged) {

            demande.message = "Changement de date de début";

        }

       

        Ebean.update(demande);

       

        demande.localisation.statut = generateNewStatut(Statut.NOUVEAU);

    }

   

    public class Demande {

        @Id

        public Long id;

       

        @JsonDeserialize(using = LocalDateDeserializer.class)

        @JsonSerialize(using = LocalDateSerializer.class)

        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DateUtils.DD_MM_YYYY)

        public LocalDate dateDebut;

   

        @JsonDeserialize(using = LocalDateDeserializer.class)

        @JsonSerialize(using = LocalDateSerializer.class)

        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DateUtils.DD_MM_YYYY)

        public LocalDate dateFin;

       

        @OneToOne(cascade = CascadeType.ALL)

        public Localisation localisation;

       

        public String commentairePcc;

       

        public String message;

    }

It works !

 

Here, the same code example with ebean version 12.16.2 :


    public static void main(String args[]) {

        Demande demande; // come from user input

        Demande originalDemande; // come from database

        // demande and originalDemande have different dateDebut

       

        processDemande(demande, originalDemande);

    }

   

    public void processDemande(Demande originalDemande, Demande demande) {

        boolean hasDateChanged = !besoin.getDateDebut().equals(originalBesoin.getDateDebut());

        if (hasDateChanged) {

            demande.setMessage("Changement de date de début");

        }

       

        DB.update(demande);

       

        demande.getLocalisation().setStatut(generateNewStatut(Statut.NOUVEAU));

    }

   

    public class Demande {

        @Id

        private Long id;

       

        @JsonDeserialize(using = LocalDateDeserializer.class)

        @JsonSerialize(using = LocalDateSerializer.class)

        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DateUtils.DD_MM_YYYY)

        private LocalDate dateDebut;

   

        @JsonDeserialize(using = LocalDateDeserializer.class)

        @JsonSerialize(using = LocalDateSerializer.class)

        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DateUtils.DD_MM_YYYY)

        private LocalDate dateFin;

       

        @OneToOne(cascade = CascadeType.ALL)

        private Localisation localisation;

       

        private String commentaire;

       

        private String message;

       

        public void setId(Long id) { this.id = id; }

       

        public Long getId() { return this.id; }

       

        public LocalDate getDateDebut() { return dateDebut; }

   

        public void setDateDebut(LocalDate dateDebut) { this.dateDebut = dateDebut; }

   

        public LocalDate getDateFin() { return dateFin; }

   

        public void setDateFin(LocalDate dateFin) { this.dateFin = dateFin; }

       

        public void setCommentaire(String commentaire) { this.commentaire; }

       

        public getCommentaire() { return this.commentaire; }

       

        public void setMessage(String message) { this.message; }

       

        public getMessage() { return this.message; }

    }

This no longer works.

When I debug my code, I get the following error when I call « demande.getLocalisation() » in the « processDemande » method :

npe.png

If I continue debugging, in the EntityBeanIntercept.java class, the variable lock is null :

image_2024-06-10_110629418.png

The solution I have currently found is to add a « DB.refresh » :


    public void processDemande(Demande originalDemande, Demande demande) {

        boolean hasDateChanged = !besoin.getDateDebut().equals(originalBesoin.getDateDebut());

        if (hasDateChanged) {

            demande.setMessage("Changement de date de début");

        }

       

        DB.update(demande) ;

        DB.refresh(demande) ;

       

        demande.getLocalisation().setStatut(generateNewStatut(Statut.NOUVEAU));

    }

 

Is this the right solution ?

Rob Bygrave

unread,
Jun 10, 2024, 3:52:34 PM6/10/24
to Ebean ORM
It does not look right now.

Looking at the code the parameter order of demande and originalDemande swap ... such that the bean being updated is the one from user input? Can you check that?

Note that updating a bean that hasn't come from the database is supported but it's a bit different / called a stateless update - but this might be significant for the case as it looks like there is lazy loading going on after the update (which also suggests the bean being updated was from user input and not from the database).

Also could you include the actual full stack trace in text perhaps rather than an image. That helps indicate that this indeed was a NPE while lazy loading.


Thanks, Rob.

Loïc Calvez

unread,
Jun 11, 2024, 12:08:11 PM6/11/24
to Ebean ORM

Sorry, while simplifying the code, I swapped the two parameters. The  main  method call the  processDemande  method with the parameters in the correct order.


    public static void main(String args[]) {

        Demande demande; // come from user input

        Demande originalDemande; // come from database

        // demande and originalDemande have different dateDebut

       

        processDemande(originalDemande, demande);

    }

 

The error in my log file :


java.lang.NullPointerException: null

        at io.ebean.bean.EntityBeanIntercept.loadBean(EntityBeanIntercept.java:833)

        at io.ebean.bean.EntityBeanIntercept.preGetter(EntityBeanIntercept.java:946)

        at models.demande.Demande._ebean_get_localisation(Demande.java:6)

        at models.demande.Demande.getLocalisation(Demande.java:1327)

        at services.demande.DemandeService.processDemande(DemandeService.java:2093)

        at controllers.demande.DemandeController.updateDemande(DemandeController.java:911)

        at controllers.demande.DemandeController.update_aroundBody10(DemandeController.java:684)

        at controllers.demande.DemandeController.update_aroundBody11$advice(DemandeController.java:36)

        at controllers.demande.DemandeController.update(DemandeController.java:1)

        at router.Routes$$anonfun$routes$1.$anonfun$applyOrElse$750(Routes.scala:13891)

        at play.core.routing.HandlerInvokerFactory$$anon$8.resultCall(HandlerInvoker.scala:150)

        at play.core.routing.HandlerInvokerFactory$$anon$8.resultCall(HandlerInvoker.scala:149)

        at play.core.routing.HandlerInvokerFactory$JavaActionInvokerFactory$$anon$3$$anon$4$$anon$5.invocation(HandlerInvoker.scala:115)

        at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:119)

        at play.http.DefaultActionCreator$1.call(DefaultActionCreator.java:33)

        at controllers.utils.ConfigurationContext.call(ConfigurationContext.java:75)

        at controllers.utils.UtilisateurContext.call(UtilisateurContext.java:96)

        at play.mvc.Security$AuthenticatedAction.lambda$call$2(Security.java:61)

        at java.base/java.util.Optional.map(Optional.java:265)

        at play.mvc.Security$AuthenticatedAction.call(Security.java:61)

        at utils.Journal$JournalAction.call(Journal.java:76)

        at play.core.j.JavaAction.$anonfun$apply$8(JavaAction.scala:175)

        at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:659)

        at scala.util.Success.$anonfun$map$1(Try.scala:255)

        at scala.util.Success.map(Try.scala:213)

        at scala.concurrent.Future.$anonfun$map$1(Future.scala:292)

        at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:33)

        at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:33)

        at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)

        at play.core.j.HttpExecutionContext.$anonfun$execute$1(HttpExecutionContext.scala:64)

        at play.api.libs.streams.Execution$trampoline$.execute(Execution.scala:70)

        at play.core.j.HttpExecutionContext.execute(HttpExecutionContext.scala:59)

        at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:72)

        at scala.concurrent.impl.Promise$KeptPromise$Kept.onComplete(Promise.scala:372)

        at scala.concurrent.impl.Promise$KeptPromise$Kept.onComplete$(Promise.scala:371)

        at scala.concurrent.impl.Promise$KeptPromise$Successful.onComplete(Promise.scala:379)

        at scala.concurrent.impl.Promise.transform(Promise.scala:33)

        at scala.concurrent.impl.Promise.transform$(Promise.scala:31)

        at scala.concurrent.impl.Promise$KeptPromise$Successful.transform(Promise.scala:379)

        at scala.concurrent.Future.map(Future.scala:292)

        at scala.concurrent.Future.map$(Future.scala:292)

        at scala.concurrent.impl.Promise$KeptPromise$Successful.map(Promise.scala:379)

        at scala.concurrent.Future$.apply(Future.scala:659)

        at play.core.j.JavaAction.apply(JavaAction.scala:176)

        at play.api.mvc.Action.$anonfun$apply$4(Action.scala:82)

        at scala.concurrent.Future.$anonfun$flatMap$1(Future.scala:307)

        at scala.concurrent.impl.Promise.$anonfun$transformWith$1(Promise.scala:41)

        at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)

        at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:63)

        at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:100)

        at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)

        at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:85)

        at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:100)

        at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:49)

        at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(ForkJoinExecutorConfigurator.scala:48)

        at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)

        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)

        at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)

        at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)

        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)

[error] 2024-06-11 18:00:07,410 - modules.CustomHttpErrorHandler - Erreur Dev Serveur !

Rob Bygrave

unread,
Jun 18, 2024, 5:53:43 AM6/18/24
to eb...@googlegroups.com


This implies that the lock is null
This implies that this entity has been serialised and deserialised.

Is that the case?

That is, this issue is not related to the update() per se but that there is lazy loading being invoked on the entity bean and that entity bean has been deserialised.

Can you confirm that?


--

---
You received this message because you are subscribed to the Google Groups "Ebean ORM" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ebean+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ebean/21f19918-a5d9-40ef-9802-41b33be2e1f1n%40googlegroups.com.

Loïc Calvez

unread,
Aug 13, 2024, 5:11:37 AM8/13/24
to Ebean ORM
We had difficulties analyzing the problem, but indeed, there was a serialization. Thank you very much for your lead; we were able to fix the issue :)
Reply all
Reply to author
Forward
0 new messages