tomee-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Mark Struberg <strub...@yahoo.de>
Subject Re: Entity cant be refreshed with new list values
Date Sat, 19 Oct 2013 15:33:49 GMT

>'did not touch'? i think you are referring to checking size() or isEmpty()
Yes, sometimes you even need to iterate through those lists and touch all the lazy loading
fields of those 1:n entities if you know you need them in the frontend.



>It is interesting that you refer to it as a restriction. do you 

> prefer/recommend this approach, or another approach?
In those cases I'd go d' accord with Romain and suggest using DTOs.



> I think I read somewhere how size() and isEmpty() will retrieve the 

> data, but now I know, you must do this inside @EJB. right?

Yes, you can think of an @Stateless EJB as a CDI bean which has (amongst others) a CDI @Transactional
interceptor [1] automatically applied to it. What happens is kind of what I show on page 31
in [2]. Simplified, but you get the idea I hope. 


This makes it obvious that once the method you invoke on your (outermost) EJB returns, then
the interceptor will commit the transaction and close the EntityManager again. Please note
that the EntityManager you get with @PersistenceContext is NOT a native JPA EntityManager
but just a facade which delegates to the _real_ EM (per Thread and EJB invocation). And this
'real' EM will gets closed in the Transactional interceptor, which means all the entities
loaded by it will automatically get detached in that moment. 
I hope it's clear now why lazy loading and other stuff _outside_ the EJB does not work as
expected ;)

You should nontheless be able to change values in the entites and those changes must get reflected
to the database if you later em.merge it inside an EJB. Oh btw, an error which also happens
pretty often is that em.merge gets used the wrong way:

SomeStuff mergedAndManagedEntity = em.merge(detachedEntity);


the PARAMETER entity will NOT become managed! Only the return value is managed!


>are you recommending this for only OpenJPA users? 

> I'm using 
EclipseLink and (Apache) Derby. I think I read 

> about this before 
somewhere; is the 'optlock' part of 

> Java EE implementation or just for 
OpenJPA users?

@Version is a *very* important part of the JPA spec itself. 

I'm not sure why, but this is something which is often missing in applications.
Maybe because almost none of the JavaEE samples on the Oracle page and in JavaEE talks mention
this and other important stuff (like the DTO and EntityManager details explained above). 


I've had this discussion with Adam Bien in the past (whom I enjoy sharing conference slots
with regularly). I recommend watching his talks because they are very enthusiastic and show
a lot of the power of JavaEE. Especially if you have some junior devs and like them to get
the basic ideas and power of JavaEE or if you like to get a good overview about new features
of the latest JavaEE version.

But he also tends to over-simply his samples and leaves out lots of very important parts -
like the Oracle/Sun docs do as well. 

Adams argument is pretty straight forward. Of course he knows all those nasty details, but
if he would go into those details then he could only explain one or two single features of
JavaEE during each sessions. And he would utterly confuse listeners by explaining details
which they do not get anyway. I can completely understand his position, but I believe for
creating *real* applications, you need to know about all those gory details :/
That's the reason why I regularly do 'Pitfalls in JavaEE' kind of lectures on javaeesummit
and other events.


Oki, back to @Version.
This is what provides you with locking.
There are 2 ways of locking in the database

a.) pessimistic locking, also known as database row locking (if you are happy it only locks
the row in a table. Could also lock the whole table depending on indexes, etc). This requires
an open database connection, so nothing you usually like to do in a web application. See JPA
LockMode.PESSIMISTIC_READ, etc;

b.) optimistic locking. This is what you usually use in web apps. There is no database locking
involved. Imagine you have a CUSTOMER table with the following columns:
* id* name
* birthdate

Now imagine a secretary A opens customer 'Jack' with id=1 and changes the name to 'Jill'.
He lets the edit page open for around 4 hourse because he went to lunch. In the meantime another
secretary B opened the same row, changed the birthdate and stores it. Finally secretary A
saves his edit page. What happens is 

UPDATE CUSTOMER set name='Jill', birthdate='old' where id =1;
which means that all the changes done by secretary B get overwritten and are ultimately lost!

With optimistic locking you would not have this problem. You just need an additional 'version'
integer column

* id
* version
* name
* birthdate

and the update performed by JPA will look like this:

UPDATE CUSTOMER set name='Jill', birthdate='old', version=:oldversion+1 where id = 1 and version
= :oldversion;

where the oldversion is the version number (e.g. 1) at the time you did load it from the database.
If anyone has updated the row and incremented the version in the meantime then your update
will fail and you could detect this as OptimisticLockException and force the 2nd user to first
reload the values from the DB again and then apply his changes on top of the new data. That
way you do not loose information.

I've now uploaded one of my half day lectures to my people account [3]. Hope you can find
some valuable info in there



[1] http://deltaspike.apache.org/jpa.html

[2] http://people.apache.org/~struberg/jax2013/cdi-deep-dive_1.1_jax2013.pdf
[3] http://people.apache.org/~struberg/eesummit2013/Java%20EE%20Summit%20-%20pitfalls%20in%20EE.pdf



>________________________________
> From: "Howard W. Smith, Jr." <smithh032772@gmail.com>
>To: users@tomee.apache.org; Mark Struberg <struberg@yahoo.de> 
>Sent: Saturday, 19 October 2013, 14:06
>Subject: Re: Entity cant be refreshed with new list values
> 
>
>
>wow, interesting response, (thanks) Mark! responses inline..
>
>
>
>
>On Sat, Oct 19, 2013 at 3:16 AM, Mark Struberg <struberg@yahoo.de> wrote:
>
>Much easier solution:
>>mark the fields you don't like to persist as
>>@javax.persistence.Transient
>>
>
>
>interesting, did not know this.
> 
>
>>In standard EJBs you will get the entitymanager-per-transaction pattern. Which means
that any lazy loading field or relation you did not touch in your EJB will remain null forever.
>>
>
>
>i learned this after some time and work'ed around this by populating lists/collections
in 'other layer of app' after the EJB retrieved the @Entity, where populating = use multiple
other/corresponding EJBs to populate each related List/Collection of @Entity. Bad design/performance,
I'm sure.
>
>
>'did not touch'? i think you are referring to checking size() or isEmpty() on Lists/collections
that belong/related to @Entity... before @Entity is returned from @EJB method. I think I read
somewhere how size() and isEmpty() will retrieve the data, but now I know, you must do this
inside @EJB. right?
> 
>If you are aware of this restriction, then all is fine and you can use EJBs. Nowadays
a DTO is nothing more than making sure that you touch all the fields an info you need in the
other layer of your app,
>>
>
>
>It is interesting that you refer to it as a restriction. do you prefer/recommend this
approach, or another approach? I will have to see if I can improve my app a bit by keeping
this in mind (as I have bandwidth to do so). thanks.
>
>
>
>>Btw, you should add a
>>
>>@Version
>>private Integer optlock;
>>
>>to all your entities. Otherwise you will not have any locking in the database. And
of course if you use DTOs then you will also need to set this info into your DTO and do a
manual comparison in your EJBs to make sure the entitiy did not get changed in the meantime.
>>
>
>
>are you recommending this for only OpenJPA users? I'm using EclipseLink and (Apache) Derby.
I think I read about this before somewhere; is the 'optlock' part of Java EE implementation
or just for OpenJPA users?
>
>
>
>
>
>

Mime
View raw message