Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 407834 - Persisting an entity with a column annotated @CacheIndex throws org.eclipse.persistence.exceptions.DescriptorException
Summary: Persisting an entity with a column annotated @CacheIndex throws org.eclipse.p...
Status: RESOLVED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 7
: P2 critical with 17 votes (vote)
Target Milestone: ---   Edit
Assignee: Lukas Jungmann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-05-12 17:52 EDT by Martin S. CLA
Modified: 2022-06-09 10:04 EDT (History)
12 users (show)

See Also:


Attachments
Bug Fix (1.80 KB, patch)
2014-03-19 11:58 EDT, Tomas Kraus CLA
no flags Details | Diff
Bug fix and jUnit test (4.24 KB, patch)
2014-03-21 11:01 EDT, Tomas Kraus CLA
no flags Details | Diff
Bug fix and jUnit test (4.24 KB, patch)
2014-03-24 05:56 EDT, Tomas Kraus CLA
no flags Details | Diff
jUnit test results (327.47 KB, text/html)
2014-03-24 05:57 EDT, Tomas Kraus CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Martin S. CLA 2013-05-12 17:52:43 EDT
Prelude:

EclipseLink 2.4.1 @ Glassfish 3.1.2.2
Java EE 6.
EJB container managed entity manager.
Weaving enabled.

------------------------

1.) Take this as an excerpt of an entity. The field "email" has a getter and setter of coure.

...
@Column(name = "email", nullable = false, updatable = false, length = 128)
@CacheIndex(updateable = false)
private String email;
...

Whenever trying to persist that entity via entity manager I get an "org.eclipse.persistence.exceptions.DescriptorException" with message "Missing mapping for field email". 

The exception occurs although entity is persisted correctly to the DB. 

------------------------

2.) BUT more worse, the exception can have side effects. Eclipse Link Shared Memory Cache can become corrupted.

Let´s take the procedure from above: 

In ONE transaction X entity A with field "email" gets persisted ("em.persist(entityA)") and another persistent entity B gets removed ("em.remove(entityB)"). The tranaction is executed successfully in the DB.

Directly (several seconds) afterwards one transaction Y tries to retrieve entity B via "em.find(entityB)" and gets the entity from the cache although this cannot be possible because it was deleted in transaction X (and of course is no longer existent in DB)!
Comment 1 James Sutherland CLA 2013-05-27 08:23:54 EDT
Please include the full exception stack trace, and attach a test case, or at least the code used.

Could be an issue with the, updatable = false in the @Column, can you try removing this please.

The second issue is most likely caused by the first, the error is occurring during the merge, so the merge does not complete, leaving a partial merge (and object left in cache).
Comment 2 James Sutherland CLA 2013-05-27 09:50:20 EDT
Are you also setting insertable=false?  or getting errors during descriptor initialization?
Comment 3 Tom Ware CLA 2013-06-11 09:45:40 EDT
Setting target and priority.  See the following page for the meanings of these fields:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines

Community: Please vote for this bug if it is important to you.  Votes are one of the main criteria we use to determine which bugs to fix next.
Comment 4 Martin S. CLA 2013-11-02 19:16:59 EDT
I am now using EclipseLink 2.5.0 @ Glassfish 4.0. The problem still exists.

----------------------------------------------

Removing "updatable = false" from @Column did not make any difference - still getting the same exception. And I am also not setting "insertable=false" on the column. 

Furthermore I am not getting any errors during descriptor initialization.

----------------------------------------------

This is an excerpt of the entity:

@Entity
@Table(name = "registration")
@Cache(type = CacheType.SOFT_WEAK, size = 25)
public class Registration implements Serializable {

//............

@Column(name = "email", length = 64, nullable = false)
@NotNull
@Size(min = 6, max = 64)
@Pattern(regexp = "\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,16}\\b")
@Index(unique = true)
@CacheIndex(updateable = false)
private String email;

//............

}

----------------------------------------------

This is an excerpt of the EJB:

@Stateless
@LocalBean
public class RegistrationService {

    @PersistenceContext
    private EntityManager em;

    
    @PermitAll
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public String register(.....) {
        Registration registration = new Registration();

        //..... calling some setters of registration 

        registration.setEmail(email);        

        em.persist(registration);
        em.flush();

        return registration.getEmail();
    }
}

----------------------------------------------

This is the full stacktrace:

Local Exception Stack: 
Exception [EclipseLink-45] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Missing mapping for field [registration.email].
Descriptor: RelationalDescriptor(de.blacksmiths.snc.backend.registration.entity.Registration --> [DatabaseTable(registration)])
	at org.eclipse.persistence.exceptions.DescriptorException.missingMappingForField(DescriptorException.java:981)
	at org.eclipse.persistence.internal.descriptors.ObjectBuilder.extractValueFromObjectForField(ObjectBuilder.java:2910)
	at org.eclipse.persistence.descriptors.CachePolicy.indexObjectInCache(CachePolicy.java:889)
	at org.eclipse.persistence.internal.descriptors.ObjectBuilder.mergeChangesIntoObject(ObjectBuilder.java:3776)
	at org.eclipse.persistence.internal.sessions.MergeManager.mergeChangesOfWorkingCopyIntoOriginal(MergeManager.java:839)
	at org.eclipse.persistence.internal.sessions.MergeManager.mergeChangesOfWorkingCopyIntoOriginal(MergeManager.java:698)
	at org.eclipse.persistence.internal.sessions.MergeManager.mergeChanges(MergeManager.java:309)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.mergeChangesIntoParent(UnitOfWorkImpl.java:3278)
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.mergeChangesIntoParent(RepeatableWriteUnitOfWork.java:376)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.mergeClonesAfterCompletion(UnitOfWorkImpl.java:3415)
	at org.eclipse.persistence.transaction.AbstractSynchronizationListener.afterCompletion(AbstractSynchronizationListener.java:217)
	at org.eclipse.persistence.transaction.JTASynchronizationListener.afterCompletion(JTASynchronizationListener.java:79)
	at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:557)
	at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:854)
	at com.sun.ejb.containers.EJBContainerTransactionManager.completeNewTx(EJBContainerTransactionManager.java:719)
	at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:503)
	at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4475)
	at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2009)
	at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1979)
	at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220)
	at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
	at com.sun.proxy.$Proxy336.register(Unknown Source)
	at de.blacksmiths.snc.backend.registration.boundary.__EJB31_Generated__RegistrationService__Intf____Bean__.register(Unknown Source)
	at de.blacksmiths.snc.frontend.registration.bean.RegistrationController.registerUser(RegistrationController.java:75)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at com.sun.el.parser.AstValue.invoke(AstValue.java:275)
	at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
	at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
	at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
	at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
	at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
	at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
	at javax.faces.component.UICommand.broadcast(UICommand.java:315)
	at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
	at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
	at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
	at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
	at de.blacksmiths.snc.frontend.auth.filter.AbstractConverseAuthConstraintFilter.doFilter(AbstractConverseAuthConstraintFilter.java:68)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
	at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
	at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
	at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
	at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
	at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
	at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
	at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
	at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
	at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
	at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
	at java.lang.Thread.run(Thread.java:722)
]]

[2013-11-02T23:58:49.974+0100] [glassfish 4.0] [WARNING] [enterprise_distributedtx.after_completion_excep] [javax.enterprise.resource.jta.com.sun.enterprise.transaction] [tid: _ThreadID=90 _ThreadName=http-listener-1(2)] [timeMillis: 1383433129974] [levelValue: 900] [[
  DTX5015: Caught exception in afterCompletion() callback:
javax.persistence.PersistenceException: Exception [EclipseLink-45] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Missing mapping for field [registration.email].
Descriptor: RelationalDescriptor(de.blacksmiths.snc.backend.registration.entity.Registration --> [DatabaseTable(registration)])
	at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl$1.handleException(EntityManagerSetupImpl.java:692)
	at org.eclipse.persistence.transaction.AbstractSynchronizationListener.handleException(AbstractSynchronizationListener.java:275)
	at org.eclipse.persistence.transaction.AbstractSynchronizationListener.afterCompletion(AbstractSynchronizationListener.java:242)
	at org.eclipse.persistence.transaction.JTASynchronizationListener.afterCompletion(JTASynchronizationListener.java:79)
	at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:557)
	at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:854)
	at com.sun.ejb.containers.EJBContainerTransactionManager.completeNewTx(EJBContainerTransactionManager.java:719)
	at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:503)
	at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4475)
	at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2009)
	at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1979)
	at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220)
	at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
	at com.sun.proxy.$Proxy336.register(Unknown Source)
	at de.blacksmiths.snc.backend.registration.boundary.__EJB31_Generated__RegistrationService__Intf____Bean__.register(Unknown Source)
	at de.blacksmiths.snc.frontend.registration.bean.RegistrationController.registerUser(RegistrationController.java:75)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at com.sun.el.parser.AstValue.invoke(AstValue.java:275)
	at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
	at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
	at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
	at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
	at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
	at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
	at javax.faces.component.UICommand.broadcast(UICommand.java:315)
	at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
	at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
	at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
	at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
	at de.blacksmiths.snc.frontend.auth.filter.AbstractConverseAuthConstraintFilter.doFilter(AbstractConverseAuthConstraintFilter.java:68)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
	at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
	at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
	at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
	at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
	at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
	at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
	at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
	at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
	at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
	at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
	at java.lang.Thread.run(Thread.java:722)
Caused by: Exception [EclipseLink-45] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Missing mapping for field [registration.email].
Descriptor: RelationalDescriptor(de.blacksmiths.snc.backend.registration.entity.Registration --> [DatabaseTable(registration)])
	at org.eclipse.persistence.exceptions.DescriptorException.missingMappingForField(DescriptorException.java:981)
	at org.eclipse.persistence.internal.descriptors.ObjectBuilder.extractValueFromObjectForField(ObjectBuilder.java:2910)
	at org.eclipse.persistence.descriptors.CachePolicy.indexObjectInCache(CachePolicy.java:889)
	at org.eclipse.persistence.internal.descriptors.ObjectBuilder.mergeChangesIntoObject(ObjectBuilder.java:3776)
	at org.eclipse.persistence.internal.sessions.MergeManager.mergeChangesOfWorkingCopyIntoOriginal(MergeManager.java:839)
	at org.eclipse.persistence.internal.sessions.MergeManager.mergeChangesOfWorkingCopyIntoOriginal(MergeManager.java:698)
	at org.eclipse.persistence.internal.sessions.MergeManager.mergeChanges(MergeManager.java:309)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.mergeChangesIntoParent(UnitOfWorkImpl.java:3278)
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.mergeChangesIntoParent(RepeatableWriteUnitOfWork.java:376)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.mergeClonesAfterCompletion(UnitOfWorkImpl.java:3415)
	at org.eclipse.persistence.transaction.AbstractSynchronizationListener.afterCompletion(AbstractSynchronizationListener.java:217)
	... 63 more
]]
Comment 5 frederic juaneda CLA 2013-12-03 10:03:10 EST
Hi,

I am facing the very same problem actually. I confirm that annotating a field that is properly mapped with @Column(name="first_name") ends up with an exception being raised at runtime:
Exception Description: Missing mapping for field [xxx.first_name]
Specifying updatable / nullable does not change anything.
Specifying @CacheIndex at attribute or class level ends up badly in the very same way.

I am using Eclipse Persistence Services - version 2.5.1.v20130918-f2b9fc5 under Mac OS X 10.9.

Many thanks for helping fixing this defect.
;o)
Comment 6 Jonathan Fisher CLA 2014-02-17 01:57:38 EST
Confirmed in 2.5.1 for me as well, no matter if I annotate the entity or field, or setting insertable/updateable to false.
Comment 7 Jonathan Fisher CLA 2014-02-24 22:40:15 EST
Just curious... is there _any_ scenario where @CacheIndex works? I've tried a handful of versions with different scenarios... It seems to be broken in every case.
Comment 8 Tomas Kraus CLA 2014-03-19 11:58:15 EDT
Created attachment 241019 [details]
Bug Fix

Looks like there was no check to set field.useUpperCaseForComparisons(...) in CacheIndex code.

In org.eclipse.persistence.internal.jpa.metadata.ORMetadata#setFieldName(DatabaseField, String) there is following piece of code:
        if (m_project.useDelimitedIdentifier()) {
            field.setUseDelimiters(true);
        } else if (m_project.getShouldForceFieldNamesToUpperCase() && ! field.shouldUseDelimiters()) {
            field.useUpperCaseForComparisons(true);
        }
Which passes MetadataProject information to field.

Now back to CacheIndex. In [CachePolicy].addCacheIndex(String ...) I saw no MetadataProject reference and no session where it's stored too so I did DatabaseField initialization in CacheIndexMetadata#process(MetadataDescriptor , String) where MetadataProject is available.

Passing MetadataProject into addCacheIndex(String ...) to do it inside will change public method prototype so I did not do it that way.

I'm not sure if field.setUseDelimiters(true) makes sense too in CacheIndex code. If so, please let me know and I'll add it too.
Comment 9 Tomas Kraus CLA 2014-03-21 11:01:38 EDT
Created attachment 241102 [details]
Bug fix and jUnit test

Now there is the same check as in ORMetadata#setFieldName(...) method including delimiter check and field values are updated to match values set in ORMetadata#setFieldName(...). So hashCode() of both filed instances is the same and mapping is found.

jUnit is simple - I just found existing @CacheIndex in org.eclipse.persistence.testing.models.jpa.advanced.Buyer entity class and changed its column name to lower case. This broke some 80 existing jUnit tests with the same exception - mapping for this column was not found - and they got fixed with applying this fix.
Comment 10 Tomas Kraus CLA 2014-03-24 05:56:55 EDT
Created attachment 241160 [details]
Bug fix and jUnit test
Comment 11 Tomas Kraus CLA 2014-03-24 05:57:58 EDT
Created attachment 241161 [details]
jUnit test results
Comment 12 Gordon Yorke CLA 2014-03-27 12:30:59 EDT
Patch reviewed and checked in.
Comment 13 Jonathan Fisher CLA 2014-03-30 23:58:56 EDT
Thank you!
Comment 14 Joachim Kanbach CLA 2014-08-11 08:02:04 EDT
I just ran into this bug with the EL build 2.5.2.v20140319 (contained in the latest GlassFish nightly). So in order to fix it, I tried to replace EL with the latst nightly 2.5.3.v20140806, assuming the patch is already a part of it. But the bug still occurs. I'm quite positive that the nightly does get used due to this log:

Exception [EclipseLink-45] (Eclipse Persistence Services - 2.5.3.v20140806-585eeac): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Missing mapping for field [public.user.login].
Descriptor: RelationalDescriptor(com.acme.User --> [DatabaseTable(public.user)])
	at org.eclipse.persistence.exceptions.DescriptorException.missingMappingForField(DescriptorException.java:983)
	at org.eclipse.persistence.internal.descriptors.ObjectBuilder.extractValueFromObjectForField(ObjectBuilder.java:3208)
	at org.eclipse.persistence.descriptors.CachePolicy.indexObjectInCache(CachePolicy.java:917)
	[...]

I notice two differences with the scenario described by the OP: first, I'm annotating the class and not the property with @CacheIndex; second, I'm using property access (@Access( AccessType.PROPERTY )), so I annotated the getter method instead of the field. The bug fix seems to be based on correct *field* initialization, so maybe the property access causes this ...?
Comment 15 Lukas Jungmann CLA 2014-08-11 08:05:27 EDT
can you try 2.6.0, please? the fix doesn't seem to be in 2.5.3 according to the Target Milestone field set in this bug. thx
Comment 16 Joachim Kanbach CLA 2014-08-11 09:39:52 EDT
Thanks for your quick reply. But I'm afraid I can't get EL 2.6 to run with my GF 4 installation easily. I followed the advice given here: http://stackoverflow.com/questions/22920319/how-to-change-eclipselink-in-glashfish-4-0/22920766#22920766 to exchange the bundled EL version in GF. With EL 2.5.3, this went smoothly, but with 2.6, something is wrong with the classpath:

java.lang.Exception: java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.apache.catalina.LifecycleException: java.lang.ClassNotFoundException: org.glassfish.jersey.moxy.json.MoxyJsonConfig

If I remove the ContextResolver where MoxyJsonConfig is used, I can at least deploy my application, but instead I get java.lang.ClassNotFoundException: org.eclipse.persistence.jaxb.JAXBContextFactory resp. java.lang.NoClassDefFoundError: com/fasterxml/jackson/module/jaxb/JaxbAnnotationIntrospector on JAXB XML/JSON binding invocations. This is after having given the server some time to rebuild the OSGi cache, as recommended.

I couldn't find a specific guide on how to upgrade to EL 2.6, so something may have gone wrong there.
Comment 17 Lukas Jungmann CLA 2014-08-11 10:21:17 EDT
I see. In this particular case can you try to take org/eclipse/persistence/internal/jpa/metadata/cache/CacheIndexMetadata.class from 2.6.0 and copy it into 2.5.x you have? (just back up your original jar first just in case)
Comment 18 Joachim Kanbach CLA 2014-08-11 10:53:57 EDT
Thanks for the hint - I think I'm onto something now.

I patched org.eclipse.persistence.jpa.jar by replacing only org/eclipse/persistence/internal/jpa/metadata/cache/CacheIndexMetadata.class, like you said. But this didn't seem to have an effect at first, I still got the "Missing Mapping" exception. Then I realized that there was actually another difference in my setup from OP's:

Before, I was using this annotation: @CacheIndex( columnNames = { "login" }, updateable = false ), annotating the class. I had taken the columnNames attribute from the documentation at https://www.eclipse.org/eclipselink/documentation/2.5/jpa/extensions/a_cacheindex.htm.

So I tried to move it to the field/getter instead and leave out the "columnNames" attribute. And finally the exception went away. I tested it with both field and property access, both of which worked.

And to be sure, I replaced org.eclipse.persistence.jpa.jar with my 2.5.2 backup again. In this case, it makes no difference if I use the annotation on the class or field/getter, or with the "columnNames" attribute or without it - the exception occurs consistently.

So my conclusion is that using the annotation on the class level/with the columnNames attribute still is buggy.
Comment 19 Joachim Kanbach CLA 2014-08-11 10:55:34 EDT
I forgot to say, I could verify that the annotation worked with the patched JAR not only by the absence of the exception but also by doing a getSingleResult() on a previously queried instance, which did not trigger an SQL SELECT indeed.
Comment 20 Lukas Jungmann CLA 2014-08-11 10:57:46 EDT
thanks for checking this. Based on your conclusion this should be reopened...
Comment 21 Jonathan Fisher CLA 2014-10-27 18:40:08 EDT
Two questions... First, can anyone point me to the patch we can apply to get this working?

Second, any idea what further might be wrong so we can possibly look into it ourselves?
Comment 22 Jonathan Fisher CLA 2014-11-10 13:23:10 EST
To anyone else wondering... in 2.6.0-M3 @CacheIndex DOES seem to work just fine when annotated on individual fields.
Comment 23 Joachim Kanbach CLA 2014-11-18 04:26:34 EST
Jonathan, annotating fields had been fixed previously already on the 2.6.x branch (but not backported to 2.5.x). The bug report was reopened because annotating the class still caused the Exception. I didn't retest this with a new nightly build, but since there were no updates posted here, I guess nothing changed yet.

Maybe the documentation and example code should simply be changed at https://www.eclipse.org/eclipselink/documentation/2.5/jpa/extensions/a_cacheindex.htm, removing the class annotation as a possible option ...?
Comment 24 Kartik Shankar CLA 2015-11-16 18:55:24 EST
Applying the similar fix in the else block of the process method of CacheIndexMetadata fixes the issue for the class level @CacheIndex annotation. I validated with a cache index declared at the entity level and tied to two columns. Can the equivalent be rolled into a target release?

---

else {
            CacheIndex index = new CacheIndex();
            if (this.updateable != null) {
                index.setIsUpdateable(this.updateable);
            }
            for (String column : m_columnNames) {
            	DatabaseField field = new DatabaseField(column);
                if (m_project.useDelimitedIdentifier()) {
                    field.setUseDelimiters(true);
                } else if (m_project.getShouldForceFieldNamesToUpperCase() && !field.shouldUseDelimiters()) {
                    field.useUpperCaseForComparisons(true);
                }
                index.addField(field);
            }
            descriptor.getClassDescriptor().getCachePolicy().addCacheIndex(index);            
        }
Comment 25 Eclipse Genie CLA 2018-03-22 06:37:38 EDT
GitHub Pull Request 14 created by [lukasj]
https://github.com/eclipse-ee4j/eclipselink/pull/14
Comment 26 Eclipse Genie CLA 2018-03-27 10:46:14 EDT
GitHub Pull Request 30 created by [lukasj]
https://github.com/eclipse-ee4j/eclipselink/pull/30
Comment 27 Eclipse Webmaster CLA 2022-06-09 10:04:38 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink