The statement dynamicRecordWeaver.weave(); will
trigger the refreshMetadata using the following API
JpaEntityManagerFactory.class.cast(localContainerEntityManagerFactoryBeanCoherence.getNativeEntityManagerFactory()).refreshMetadata(null);
System.gc()
~Gaurav
On 26-07-2012 02:31 PM, Tom Ware wrote:
Hi
Gaurav,
In the code below, how does refreshMetadata get called? Where
does it get called?
-Tom
On 26/07/2012 5:53 AM, gaurav malhotra wrote:
Hi Chris/Tom,
I made the changes in my prodcut, so that mappings are created
in
SessionCustomizer. What I see when the refreshMetadata() is
called, first
entityManager creation result's in re-triggering of the
SessionCustomizer ( why
on entityManager creation because
shouldGetSessionOnCreateFactory is set to false).
NOTE :- I am using ecipselink 2.3.2-13771165 (13771165 is the
patch number)
along with TLG 12.1.1.13771165 with coherence 3.7. Also entity
in question
CtrClaimDomain is decorated as @Cacheable(false)
But my below test case again fails on the highlighted line
@Autowired
@Qualifier("entityManagerFactory")
private LocalContainerEntityManagerFactoryBean
localContainerEntityManagerFactoryBean;
@Autowired
private DynamicRecordWeaver dynamicRecordWeaver;
EntityManagerFactory entityManagerFactory =
localContainerEntityManagerFactoryBean.getNativeEntityManagerFactory();
// Make a change to your data model that would cause the
mappings to change +
emf.refreshMetadata()
dynamicRecordWeaver.weave();
EntityManager em1 = entityManagerFactory.createEntityManager();
// Make a change to your data model that would cause the
mappings to change
Assert.assertNotNull(EntityManagerImpl.class.cast(em1.getDelegate()).getSession().getDescriptor(CtrClaimDomain.class).getMappingForAttributeName("pc0017"));
EntityManager em2 = entityManagerFactory.createEntityManager();
_*Assert.assertNotNull(EntityManagerImpl.class.cast(em2.getDelegate()).getSession().getDescriptor(CtrClaimDomain.class).getMappingForAttributeName("pc0017"));*_
int size1 =
EntityManagerImpl.class.cast(em1.getDelegate()).getSession().getDescriptor(CtrClaimDomain.class).getMappings().size();
int size2 =
EntityManagerImpl.class.cast(em2.getDelegate()).getSession().getDescriptor(CtrClaimDomain.class).getMappings().size();
Assert.assertTrue(size1==size2);
On 25-07-2012 04:53 PM, Christopher Delahunt wrote:
If the mapping is in EM1, then it means
your app is modifying the session from
EM1 directly instead of using an EclipseLink session
customizer. There may
have been confusion on what I meant by session customization -
I was refering
to this:
http://wiki.eclipse.org/Customizing_the_EclipseLink_Application_(ELUG)#Using_the_Session_Customizer_Class
using the "eclipselink.session.customizer" property to specify
a class to
change the session before it is logged in:
http://wiki.eclipse.org/Configuring_a_Session_%28ELUG%29#How_to_Configure_Customizer_Class_Using_Java
The defined customizer then will get called automatically on
any new session
created during deployment or when emf.refreshMetadata() gets
called.
On 25/07/2012 10:39 AM, gaurav malhotra wrote:
Tom,
I wrote the following test case and it fails on the
highlighted
assertion. The second time when I create the entity manager
using the
same entity manager factory, I cannot see the mapping -
pc0017.
NOTE >
localContainerEntityManagerFactoryBean.getNativeEntityManagerFactory()
will result in using the native emf and not the proxy one.
@Autowired
@Qualifier("entityManagerFactory")
private LocalContainerEntityManagerFactoryBean
localContainerEntityManagerFactoryBean;
@Autowired
private DynamicRecordWeaver dynamicRecordWeaver;
@Test
public void weave() {
EntityManager em1 =
localContainerEntityManagerFactoryBean.getNativeEntityManagerFactory().createEntityManager();
// Make a change to your data model that would cause the
mappings to
change + emf.refreshMetadata()
dynamicRecordWeaver.weave();
// Make a change to your data model that would cause the
mappings to change
Assert.assertNotNull(EntityManagerImpl.class.cast(em1.getDelegate()).getSession().getDescriptor(CtrClaimDomain.class).getMappingForAttributeName("pc0017"));
EntityManager em2 =
localContainerEntityManagerFactoryBean.getNativeEntityManagerFactory().createEntityManager();
_*Assert.assertNotNull(EntityManagerImpl.class.cast(em2.getDelegate()).getSession().getDescriptor(CtrClaimDomain.class).getMappingForAttributeName("pc0017"));*_
int size1 =
EntityManagerImpl.class.cast(em1.getDelegate()).getSession().getDescriptor(CtrClaimDomain.class).getMappings().size();
int size2 =
EntityManagerImpl.class.cast(em2.getDelegate()).getSession().getDescriptor(CtrClaimDomain.class).getMappings().size();
Assert.assertTrue(size1==size2);
}
On 25-07-2012 03:55 PM, Tom Ware wrote:
Gaurav,
Can you please confirm you ran the actual simple code
below and had
your failure. You have posted a large amount of other
code, some of
which uses sessions directly. I am hoping we can debug a
simple test
case before worrying about debugging code with additional
complexity.
If you have run exactly the code below and seen the
failure, lets
debug that exact code and leave any code that does things
like direct
session access until we have addressed the base issue.
-Tom
On 25/07/2012 9:01 AM, gaurav malhotra wrote:
Please see my comments below .....
/_Tom_/ > Get a handle on your EntityManagerFactory
(emf) and create an
EntityManager for it (em1). em1 =
emf.createEntityManager()
Make a change to your data model that would cause the
mappings to change
Call emf.refreshMetadata() and confirm that your code
that adds
mappings is
getting called
_/Gaurav >> The above test case works/_
_/
/*Tom > *_create an new EntityManager from emf. em2
emf.createEntityManager()
Compare the mappings in em1 and em2. I would expect the
changed
mappings to
appear in em2.
/_Gaurav >> The above test case fails_/
On 25-07-2012 02:38 PM, Tom Ware wrote:
Let me suggest a simple test:
Get a handle on your EntityManagerFactory (emf) and
create an
EntityManager
for it (em1). em1 = emf.createEntityManager()
Make a change to your data model that would cause the
mappings to
change
Call emf.refreshMetadata() and confirm that your code
that adds
mappings is
getting called
create an new EntityManager from emf. em2
emf.createEntityManager()
Compare the mappings in em1 and em2. I would expect
the changed
mappings to
appear in em2.
On 25/07/2012 8:33 AM, gaurav malhotra wrote:
Hi Tom,
I also checked the spring entity manager creations
(JpaTemplate).
Please see the
code below. getEntityManagerFactory() basically uses
the same
entitymanager
factory, to which I added new mappings.
/**
* Create a close-suppressing proxy for the given JPA
EntityManager.
* The proxy also prepares returned JPA Query
objects.
* @param em the JPA EntityManager to create a proxy
for
* @return the EntityManager proxy, implementing all
interfaces
* implemented by the passed-in EntityManager object
(that is,
* also implementing all provider-specific extension
interfaces)
* @see javax.persistence.EntityManager#close
*/
protected EntityManager
createEntityManagerProxy(EntityManager em) {
Class[] ifcs = null;
EntityManagerFactory emf =
getEntityManagerFactory();
if (emf instanceof EntityManagerFactoryInfo) {
Class entityManagerInterface =
((EntityManagerFactoryInfo)
emf).getEntityManagerInterface();
if (entityManagerInterface != null) {
ifcs = new Class[] {entityManagerInterface};
}
}
if (ifcs == null) {
ifcs =
ClassUtils.getAllInterfacesForClass(em.getClass());
}
return (EntityManager) Proxy.newProxyInstance(
em.getClass().getClassLoader(), ifcs, new
CloseSuppressingInvocationHandler(em));
}
On 25-07-2012 02:31 PM, gaurav malhotra wrote:
Hi Tom,
The issues currently I am facing are as follows
1) An application event (which is published on all
the nodes in
the cluster -
coherence grid aware) is triggered when there is a
need to create
a mapping.
(Works fine)
2) I have service named DynamicRecordWeaverImpl
which creates the
mappings as
follows (Please verify, if below correct way of
adding mappings.
As chris
mentioned I am not creating mapping on active
session)
NOTE >> after weave method, I can see the
need added relationship
in the
session.
@Autowired
private DynamicRecordContext dynamicRecordContext;
@Autowired
@Qualifier("entityManagerFactory")
private LocalContainerEntityManagerFactoryBean
localContainerEntityManagerFactoryBean;
/*
* (non-Javadoc)
* @see
com.oracle.healthinsurance.common.domain.internal.dyndata.components.DynamicRecordWeaver#weave()
*/
@SuppressWarnings("rawtypes")
@Override
public void weave() {
JpaEntityManagerFactory jpaEntityManagerFactory =
JpaEntityManagerFactory.class.cast(localContainerEntityManagerFactoryBean
.getNativeEntityManagerFactory());
Session session =
jpaEntityManagerFactory.getServerSession();
for (Map.Entry<Class, ClassDescriptor> entry
:
session.getDescriptors().entrySet()) {
if
(MetaModelUtil.isDynamicRecordContainer(entry.getKey()))
{
Class<? extends
DynamicRecordContainer<DynamicRecordStorable>>
dynamicRecordContainerClass = CastUtil
.uncheckedCast(entry.getKey());
Class<? extends DynamicRecordStorable>
dynamicRecordStorableClass
= CastUtil
.uncheckedCast(GenericTypeResolver.resolveTypeArgument(dynamicRecordContainerClass,
DynamicRecordContainer.class));
ClassDescriptor dynamicRecordContainerClassCd =
session.getDescriptor(dynamicRecordContainerClass);
ClassDescriptor dynamicRecordStorableClassCd =
session.getDescriptor(EclipseLinkMetadata
.getDomainClass(dynamicRecordStorableClass));
Map<String, DynamicRecordSetup>
dynamicRecordSetupMap =
dynamicRecordContext
.doGetDynamicRecordsSetup(dynamicRecordContainerClass);
for (Map.Entry<String, DynamicRecordSetup>
setupEntry :
dynamicRecordSetupMap.entrySet()) {
String fieldName = setupEntry.getKey();
DynamicRecordSetup dynamicRecordSetup =
setupEntry.getValue();
// OneToMany
oneToManyMapping(dynamicRecordContainerClassCd,
fieldName,
dynamicRecordStorableClassCd.getJavaClass());
for (FieldDetails fieldDetails :
dynamicRecordSetup.getFieldDetailsList()) {
// Add the attributes dynamicRecordStorableClass
String attributeName = fieldDetails.getCode();
String columnName = columnName(fieldDetails);
Class<?> attributeType =
attributeType(fieldDetails);
directFieldMapping(dynamicRecordStorableClassCd,
attributeName,
columnName,
attributeType);
}
}
}
}
jpaEntityManagerFactory.refreshMetadata(null);
System.gc();
3) You mentioned >> " The way
refreshMetadata works, should allow
your system
to stay live. When you call refreshMetadata, all
existing
EntityManagers
continue to operate on the previous metadata. The
new metadata is
only in
effect for new EntityManagers. "
Now I am searching for entity to which new
mappings where added.
What I found
that entityManager does not contain the newly
added mappings. I
cann't figure
out why?? It should be picked up?? so do I have
keep adding the
mappings for
each session and call refreshMetadata, this doen't
look elegant.
Is some where
there is caching of entity managers happening???
On 25-07-2012 01:56 PM, Tom Ware wrote:
Hi Gaurav,
I am assuming you've figured out how to get
refreshMetadata to
work for you
to get your mappings added. EclipseLink itself
does not provide a
mechanism
to trigger the refresh There are a number of
options open to you
depending on
how your app is architected, JMS, RMI,
ServerSentEvents,
WebSockets, Oracle
QCN/DCN combined with one of those technologies.
The way refreshMetadata works, should allow your
system to stay
live. When
you call refreshMetadata, all existing
EntityManagers continue to
operate on
the previous metadata. The new metadata is only
in effect for new
EntityManagers.
-Tom
On 24/07/2012 8:12 PM, gaurav malhotra wrote:
I understand the
problem, but I don't know how to fix it.
1) I am recording all the changes (we store
them in the database)
2) I don't know how to signal that session
needs to pick them using
refreshMetadata. Does this mean using
SessionEventAdapter?? If
yes then which
method(s) should I use. As per my
understanding refreshMetadata
should be
only
called once if there are recorded changes.
When recorded changes
has been
pushed
to session, then there is no need to
refreshMetadata. It will be
great if you
point me some code snippets.
Also, my product, is a claim processing system
(with millions of
transactions
handled in a day). What is the impact of
refreshMetadata on the
running
transactions?? We dont expect setup for the
dynamic fields
change every
another
minute or a day??
On 25-07-2012 12:04 AM, Christopher Delahunt
wrote:
Through a metadata
source repository, or the customizer
approach. Your app
must record the changes that are needed
somehow and then signal
that the
session needs to pick them up using
refreshMetadata. The app
should not
directly change the running session.
On 2012-07-24, at 5:47 PM, gaurav malhotra
<gaurav.malhotra@xxxxxxxxxx>
wrote:
Hi Chris,
It's the requirement of my product -
Dynamic Fields can be
configured at
the
runtime and should be picked up in live
application with zero
down time.
Its
for the dynamic fields I am creating the
mappings.
How to accomplish above reqirement?
~Gaurav
On 24-07-2012 11:29 PM, Christopher
Delahunt wrote:
This would occur
if the mapping has not been initialized;
initialization
occurs during session login. Earlier
posts showed mappings
being added
through a session customizer which get
called prior to login.
How and when
is this mapping added?
Calling refreshMetadata as Tom mentions
creates a new session
from the
metadata, and would call customizers on
it before logging in.
If your
customizer picks up the new mapping
changes, then that might
explain
why it
works for you, since they get
initialized with the new
session login.
It is not a good idea to make
mapping/descriptor changes to
active
sessions
after login has occurred.
On 24/07/2012 5:05 PM, gaurav malhotra
wrote:
ava.lang.NullPointerException
at
org.eclipse.persistence.mappings.ForeignReferenceMapping.valueFromRowInternal(ForeignReferenceMapping.java:2019)
at
org.eclipse.persistence.mappings.ForeignReferenceMapping.valueFromRow(ForeignReferenceMapping.java:1987)
at
org.eclipse.persistence.mappings.ForeignReferenceMapping.buildCloneFromRow(ForeignReferenceMapping.java:276)
at
org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildAttributesIntoWorkingCopyClone(ObjectBuilder.java:1548)
at
org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildWorkingCopyCloneFromRow(ObjectBuilder.java:1694)
at
org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObjectInUnitOfWork(ObjectBuilder.java:664)
at
org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:601)
at
org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:560)
at
org.eclipse.persistence.queries.ObjectLevelReadQuery.buildObject(ObjectLevelReadQuery.java:717)
at
org.eclipse.persistence.queries.ReadAllQuery.registerResultInUnitOfWork(ReadAllQuery.java:769)
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
|