persistence@glassfish.java.net

Re: Cannot see newly created object

From: Marina Vatkina <Marina.Vatkina_at_Sun.COM>
Date: Tue, 01 Jul 2008 13:26:45 -0700

Markus KARG wrote:
> Marina
>
>> Can it be that you are accessing a detached reference when you are
>> accessing it the 2nd time? If EM is transactional, and it's
>> container-managed (i.e. injected or looked up directly, not through
>> EMF), all instances become detached after commit.
>
> I thought so, too. But why not getting an Exception when doing
> em.refresh(myEntity)? Is it allowed to refresh a detached entity?

It should. Can you call em.contains() to check what does em think?

thanks,
-marina

>
> Thanks
> Markus
>
>>
>> thanks,
>> -marina
>>
>> Mitesh Meswani wrote:
>>
>>> Markus KARG wrote:
>>>
>>>> Mitesh,
>>>>
>>>>>>> This opens some other questions... You can not call em.refresh()
>>>>>>> on a detached object (results in an exception) so how is this
>>>>>>> managed entity getting into the second SB and why is there an
>>>>>>> existing Persistence Context in the second SB if you are using
>>>>>>> the default (TRANSACTION) Persistence Context type and there is
>>>>>>> not a transaction spanning the 2 SB calls?
>>>>>>> How is this second SB performing the 'lookup' ?
>>>>>>
>>>>>>
>>>>>> The SBs are not related. As I said, SB1 send JMS, JMS triggers
>>>>>> MDB. SB2 is triggered manually by the user. SB1 and SB2 are not
>>>>>> related.
>>>>>>
>>>>>> The entity is kept by SB2 (which is a stateful SB) by just keeping
>>>>>> it as a member variable. In the constructor, SB2 does
>>>>>> em.find(Entity.class, PK) to find it, and then keeps it. When the
>>>>>> client is calling SB2's business method, em.refresh(entity) is
>>>>>> performed. The object does not get detached, obviously. To be able
>>>>>> to do the em.find(PK) in the constructor, the client provides the PK.
>>>>>
>>>>>
>>>>> If SB2 is stateful SB then it explains the behavior. The default
>>>>> type of PersitenceContext for stateful bean is Extended. Hence find
>>>>> (correctly) gives you the "stale" instance and refresh solves the
>>>>> issue.
>>>>
>>>>
>>>> So that means that SLSB, SFSB and MDB have different defaults for
>>>> their PersistenceContext behaviour. In the JPA spec I found: "If the
>>>> type element is not specified, a transaction-scoped persistence
>>>> context is used.". So there must be another chapter of the spec that
>>>> contains the part with the stateful default. Can you point me to
>>>> where I can find that? :-)
>>>
>>>
>>> I was wrong. Sorry for the confusion.
>>>
>>> I think answer to Gordon's questions above should help move forward.
>>>
>>> -Mitesh
>>>
>>>>
>>>> -Markus
>>>>
>>>>>
>>>>> -Mitesh
>>>>>
>>>>>>
>>>>>> So, the entity itself is not moved around, just it's PK.
>>>>>>
>>>>>>> I can not tell you why the refresh is needed. TopLink's cache
>>>>>>> will be updated with the changes from the MDB transaction and
>>>>>>> subsequent Persistence Contexts will see this update. That is
>>>>>>> why I was asking the questions about the transactions and the
>>>>>>> types of Persistence Contexts in the Session Beans. Based on
>>>>>>> your symptoms it points to the second SB using a pre-MDB
>>>>>>> Persistence Context that contains an old version of the Parent
>>>>>>> object. Persistence Contexts are an intentionally isolated
>>>>>>> object space and will not have the changes from another
>>>>>>> Persistence Context or transaction.
>>>>>>
>>>>>>
>>>>>> So that means that you think there is a bug in TopLink? I mean,
>>>>>> either my code is right or it is not. So either there is a bug in
>>>>>> TopLink, or there is not. Since I am just a JPA novice, how should
>>>>>> I know whether to report it as a bug or not? I need you to be the
>>>>>> judge. :-)
>>>>>>
>>>>>> Thanks
>>>>>> Markus
>>>>>>
>>>>>>> --Gordon
>>>>>>>
>>>>>>> Markus KARG wrote:
>>>>>>>
>>>>>>>> Gordon,
>>>>>>>>
>>>>>>>>> Try clearing the Persistence Context in the Session Bean that
>>>>>>>>> is attempting to see the changes from the MDB before performing
>>>>>>>>> the find and the changes should then be loaded into the
>>>>>>>>> Persistence Context.
>>>>>>>>
>>>>>>>>
>>>>>>>> As I have seen the code is not exactly as I thought. The
>>>>>>>> stateful session bean that does the lookup is not keeping the PK
>>>>>>>> but the actual entity. So there is no em.find() actually. I
>>>>>>>> added a em.refresh(entity) now before the call of the lookup.
>>>>>>>> Guess what, that is working.
>>>>>>>>
>>>>>>>> But unfortunately, I have not understood why that refresh is
>>>>>>>> needed. I thought that as soon as I set both sides of the
>>>>>>>> relationship that will update the object, but it seems it does
>>>>>>>> not. Can you give me a very brief description why that refresh()
>>>>>>>> is needed? I mean, isn't TopLink's cache "seeing" that another
>>>>>>>> TX changed the number of children in the relationship?
>>>>>>>>
>>>>>>>> Thanks a lot!
>>>>>>>> Markus
>>>>>>>>
>>>>>>>>> --Gordon
>>>>>>>>>
>>>>>>>>> Markus KARG wrote:
>>>>>>>>>
>>>>>>>>>> I have not changed the transactional settings, so the defaults
>>>>>>>>>> apply in both, the SB and the EB.
>>>>>>>>>> AFAIK the default is that a TX is automatically started and
>>>>>>>>>> finished around the invocation, isn't it?
>>>>>>>>>>
>>>>>>>>>> Gordon Yorke schrieb:
>>>>>>>>>>
>>>>>>>>>>> Hello Markus
>>>>>>>>>>> What are the transactional boundaries for the listening
>>>>>>>>>>> SB? Is the em you are accessing in the listener in a
>>>>>>>>>>> transaction and reading transactional data?
>>>>>>>>>>> --Gordon
>>>>>>>>>>>
>>>>>>>>>>> Markus KARG wrote:
>>>>>>>>>>>
>>>>>>>>>>>> I forgot to mention: Exactly the same code executed from
>>>>>>>>>>>> within a session bean results in the new child beeing listed
>>>>>>>>>>>> correctly.
>>>>>>>>>>>>
>>>>>>>>>>>> So what difference is between a MDB and a SB?
>>>>>>>>>>>>
>>>>>>>>>>>> Thanks! :-)
>>>>>>>>>>>> Markus
>>>>>>>>>>>>
>>>>>>>>>>>> Markus Karg schrieb:
>>>>>>>>>>>>
>>>>>>>>>>>>> I have a strange problem and need your kind help. :-)
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> In GlassFishv2ur2, I am running a session bean that does:
>>>>>>>>>>>>>
>>>>>>>>>>>>> parent = em.find(ParentEntity.class, 1000).getSingleResult();
>>>>>>>>>>>>> parent.getChildren();
>>>>>>>>>>>>>
>>>>>>>>>>>>> which lists the content of a OneToMany relationship.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Now a message driven bean does:
>>>>>>>>>>>>>
>>>>>>>>>>>>> parent = em.find(ParentEntity.class, 1000).getSingleResult();
>>>>>>>>>>>>> child = new ChildEntity(parent); // Implicitly sets "One"-Side
>>>>>>>>>>>>> parent.getChildren().add(child); // Explicitly sets
>>>>>>>>>>>>> "Many"-Side
>>>>>>>>>>>>> em.persist(child);
>>>>>>>>>>>>>
>>>>>>>>>>>>> When I go to the DBMS, I can see the row of the new child
>>>>>>>>>>>>> including all fields. The child is correctly linked with
>>>>>>>>>>>>> the parent.
>>>>>>>>>>>>>
>>>>>>>>>>>>> But when running the listing again:
>>>>>>>>>>>>>
>>>>>>>>>>>>> parent = em.find(ParentEntity.class, 1000).getSingleResult();
>>>>>>>>>>>>> parent.getChildren();
>>>>>>>>>>>>>
>>>>>>>>>>>>> Then still I do not see the new child. To make it appear, I
>>>>>>>>>>>>> must undeploy and deploy. That is very weird, since it can
>>>>>>>>>>>>> be seen in the database table, and I have set both sides of
>>>>>>>>>>>>> the relationship as you can see in the code snippet.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Looks like a cache problem, but I just do not understand
>>>>>>>>>>>>> how to solve it.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Has anybody an idea what the cause is and how to get rid of
>>>>>>>>>>>>> it?
>>>>>>>>>>>>>
>>>>>>>>>>>>> Thanks a lot! :-)
>>>>>>>>>>>>> Markus
>>>>>>>>>>>>>
>>>>>>>>>>>>> QUIPSY QUALITY GmbH & Co. KG
>>>>>>>>>>>>> Ein Unternehmen der MES-Gruppe
>>>>>>>>>>>>> Stuttgarter Strasse 23
>>>>>>>>>>>>> D-75179 Pforzheim
>>>>>>>>>>>>> Tel: 07231-9189-52
>>>>>>>>>>>>> Fax: 07231-9189-59
>>>>>>>>>>>>> www.quipsy.de
>>>>>>>>>>>>> karg_at_quipsy.de
>>>>>>>>>>>>> Registergericht Mannheim HRA 701214
>>>>>>>>>>>>> Geschäftsführer: Nils Schroeder
>>>>>>>>>>>>>
>>>>>>>>>>>>> Diese E-Mail enthält persönliche, vertrauliche und vor
>>>>>>>>>>>>> Weitergabe geschützte Informationen und ist ausschließlich
>>>>>>>>>>>>> für den vorgesehenen o.g. Empfänger (Adressaten) bestimmt.
>>>>>>>>>>>>> Falls Sie diese E-Mail versehentlich erhalten haben und
>>>>>>>>>>>>> nicht der vorgesehene Empfänger sind, bitten wir Sie, die
>>>>>>>>>>>>> E-Mail und deren Anhänge nicht aufzubewahren, nicht zu
>>>>>>>>>>>>> vervielfältigen, nicht zu nutzen und nicht weiterzugeben.
>>>>>>>>>>>>> Bitte informieren Sie uns als Absender über diesen
>>>>>>>>>>>>> Zustellungsfehler und löschen Sie die E-Mail.
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>
>
>