[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [eclipselink-users] Virtual Metlhods | questions
|
Hi Chris,
Adding to my previous email, getActiveSession, actually uses
Eclipselink entity manager to get active session
private Session getActiveSession(EntityManager em) {
return ((EntityManagerImpl) em.getDelegate()).getActiveSession();
}
NOTE > EntityManagerImpl is actually
org.eclipse.persistence.internal.jpa.EntityManagerImpl
~Gaurav
On 25-07-2012 03:36 PM, gaurav malhotra wrote:
Hi Chris,
I will verify things you mentioned below and get back to you.
I would like to tell you, we use ReadAllQuery rather JpQL. We have
have Search Framework (which understands product domain modelling -
ubiquitous language and much more). Basically, search framework,
simply transform the SearchExpression to eclipselink expression..
ReadAllQuery
SearchResult sResult = jpaTemplate.execute(new
JpaCallback<SearchResult>() {
@Override
public SearchResult doInJpa(EntityManager em) throws
PersistenceException {
Session session = getActiveSession(em);
ReadAllQuery query = new ReadAllQuery();
// Create expression from Search Criteria use locale
as set in Context object
GenericSearchCriteria<?> gsc =
searchInput.getSearchCriteria();
gsc.setLocale(ohiBusinessContext.getLocale());
GenerateEclipseLinkExpression genExpression = new
GenerateEclipseLinkExpression(gsc,
dynamicSearchExpressionContextProvider);
ClassDescriptor cd =
session.getClassDescriptor(gsc.getPersistableClass());
// Setup how the query should be executed
setQueryExecutionConfiguration(searchInput, session,
query, gsc, genExpression, cd);
Expression exp =
genExpression.buildSelectionCriteriaFromSearchCriteria(gsc.getSearchCriteria());
// ExampleObject
query.setReferenceClass(gsc.getPersistableClass());
if (exp != null) {
logger.debug("Expression is: {0}", exp);
query.setSelectionCriteria(exp);
}
NanoStopWatch swInner = new NanoStopWatch();
swInner.start();
// Execute the query
List<Object> results =
CastUtil.castToList(session.executeQuery(query));
Is there a way to directly execute the ReadAllQuery on the
EntityManager???
~Gaurav
On 25-07-2012 03:19 PM, Christopher Delahunt wrote:
Hello Gaurav,
EclipseLink nightly testing verify that refreshMetadata does work in
the manner Tom described. What are variables that might be causing
you problems are that I see Spring is involved, and you are executing
queries directly on Sessions as shown in the few lines below from a
stack trace you sent in earlier:
at
org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1449)
at
com.oracle.healthinsurance.support.domain.service.GenericSearchDAOImpl$16.doInJpa(GenericSearchDAOImpl.java:623)
at
com.oracle.healthinsurance.support.domain.service.GenericSearchDAOImpl$16.doInJpa(GenericSearchDAOImpl.java:1)
at
org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:183)
I would have expected to just see an EclipseLink EntityManager
executing a query, not a GenericSearchDAOImpl directly
accessing/holding a session or a Spring JpaTemplate being involved.
As mentioned from Tom and I, EMF.refreshMetadata() will spawn a new
session instance that is then used for any new EntityManagers that
get created. If you can see that the customizer is getting called
and that the mappings are getting added correctly to the new session
instance, then it must be that the EntityManager you are obtaining,
em2, is not really new - for example if you are obtaining a spring
entityManager wrapper instead of using the EclipseLink EMF directly
to get an EclipseLink EntityManager instance. If it is a spring EM,
there is not telling how it obtains the underlying EM instance from
EclipseLink - chances are good it is giving you an EM cached from
prior to the refreshMetadata call.
Can you please verify how you are testing, the type of objects you
have, and what mappings are in the sessions involved in em1 and in
em2? Are the underlying serversession in the two EMs different at all?
Best Regards,
Chris
On 25/07/2012 8:31 AM, 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