[
https://issues.apache.org/jira/browse/OLINGO-45?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13807740#comment-13807740
]
Georgi edited comment on OLINGO-45 at 10/29/13 8:13 AM:
--------------------------------------------------------
As far as I can judge the problem occurs when trying to set a relation to an
Entity with multiplicity 1.
Here's the sample POST request (I'm using X-HTTP-METHOD to tunnel non standard
merge):
curl "<path>/Services(7)" -H "Origin: <path>" -H "Accept-Encoding:
gzip,deflate,sdch" -H "Accept-Language: en-US,en;q=0.8" -H "Connection:
keep-alive" -H "Pragma: no-cache" -H "MaxDataServiceVersion: 2.0" -H "Host:
localhost:8080" -H "X-HTTP-METHOD: MERGE" -H "User-Agent: Mozilla/5.0 (Windows
NT 6.1; WOW64) AppleWebKit/537.35 (KHTML, like Gecko) Chrome/27.0.1448.0
Safari/537.35" -H "Content-Type: application/json;odata=verbose" -H "Accept:
application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1"
-H "Cache-Control: no-cache" -H "Referer: <path>" -H "DataServiceVersion: 2.0"
-H "DNT: 1" --data-binary
"{\"serviceId\":7,\"member\":{\"__metadata\":{\"uri\":\"Members(6)\"}}}"
Here, the entities are Service and Member. A Member has 0..* 'services' and a
Service has 1 Member, bound by the property 'member'. The serviceId property is
the key of the Service entity.
In terms of JPA, the Service class declares:
@ManyToOne(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name = "MEMBER_ID", referencedColumnName = "MEMBER_ID")
private Member member;
So for the navigation property member, the switch edmTyped.getType().getKind()
passes through NAVIGATION and ends in the ENTITY case, with the structural type
<schemaname>.Member, correct modifier - setMember and entity set Members.
However, oDataEntryProperties map has the following entries:
{member=ODataEntryImpl [data={}, entryMetadata=EntryMetadataImpl [id=null,
etag=null, uri=Members(6), associationUris={}], mediaMetadata=MediaMetadataImpl
[sourceLink=null, etag=null, contentType=null, editLink=null],
expandSelectTree=org.apache.olingo.odata2.core.uri.ExpandSelectTreeNodeImpl@52c43db8,
containsInlineEntry=false], serviceId=7}
, and when oDataEntryProperties.get(propertyName) is invoked with propertyName
"member", we get the ODataEntryImpl entry instead of the expected by the code
List<ODataEntry>.
As for how come I need such an update: I'm using JayData as OData client
library and its NoBatch plugin due to the lack of support for $batch. JayData
sends an update of the downstream dependency relations as soon as some upstream
Entity changes (hence the update of the Service's 'member' property). NoBatch
takes care to split these into separate ordered requests. What I did was an
update of a property of the Member entity and that lead to update of all
downstream relation properties like Service's member.
was (Author: shturec):
As far as I can judge the problem occurs when trying to set a relation to an
Entity with multiplicity 1.
Here's the sample POST request (I'm using X-HTTP-METHOD to tunnel non standard
merge):
curl "<path>/Services(7)" -H "Origin: <path>" -H "Accept-Encoding:
gzip,deflate,sdch" -H "Accept-Language: en-US,en;q=0.8" -H "Connection:
keep-alive" -H "Pragma: no-cache" -H "MaxDataServiceVersion: 2.0" -H "Host:
localhost:8080" -H "X-HTTP-METHOD: MERGE" -H "User-Agent: Mozilla/5.0 (Windows
NT 6.1; WOW64) AppleWebKit/537.35 (KHTML, like Gecko) Chrome/27.0.1448.0
Safari/537.35" -H "Content-Type: application/json;odata=verbose" -H "Accept:
application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1"
-H "Cache-Control: no-cache" -H "Referer: <path>" -H "DataServiceVersion: 2.0"
-H "DNT: 1" --data-binary
"{\"serviceId\":7,\"member\":{\"__metadata\":{\"uri\":\"Members(6)\"}}}"
Here, the entities are Service and Member. A Member has 0..* 'services' and a
Service has 1 Member, bound by the property 'member'. The serviceId property is
the key of the Service entity.
In terms of JPA, the Service class declares:
@ManyToOne(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name = "MEMBER_ID", referencedColumnName = "MEMBER_ID")
private Member member;
So for the navigation property member, the switch edmTyped.getType().getKind()
passes through NAVIGATION and ends in the ENTITY case, with the structural type
<schemaname>.Member, correct modifier - setMember and entity set Members.
However, oDataEntryProperties map has the following entries:
{member=ODataEntryImpl [data={}, entryMetadata=EntryMetadataImpl [id=null,
etag=null, uri=Members(6), associationUris={}], mediaMetadata=MediaMetadataImpl
[sourceLink=null, etag=null, contentType=null, editLink=null],
expandSelectTree=org.apache.olingo.odata2.core.uri.ExpandSelectTreeNodeImpl@52c43db8,
containsInlineEntry=false], serviceId=7}
, and when oDataEntryProperties.get(propertyName) is invoked with propertyName
"member", we get the ODataEntryImpl entry instead of the expected by the code
List<ODataEntry>.
As for how come I need such an update: I'm using JayData as OData client
library and its NoBatch plugin due to the lack of support for $batch. JayData
sends an update through the dependency relations as soon as some node changes.
NoBatch takes care to split these into separate ordered requests. What I did
was an update of a property of the Member entity and that lead to update to all
downstream, related entities like Service.
> ClassCastException on Entity update
> -----------------------------------
>
> Key: OLINGO-45
> URL: https://issues.apache.org/jira/browse/OLINGO-45
> Project: Olingo
> Issue Type: Bug
> Components: odata2-jpa
> Affects Versions: 1.0.0, 1.1.0
> Reporter: Georgi
> Assignee: Chandan V.A
>
> You might want to doublecheck the logic in
> org.apache.olingo.odata2.processor.core.jpa.access.data.JPAEntity:write(final
> Map<String, Object> oDataEntryProperties, final boolean isCreate)
> On line 141 there's an explicit cast to List<ODataEntry>. However I found out
> that during update, when the property is a 1:1..0 relation to another Entity,
> the returned type is ODataEntry. And that causes the ClassCastException.
> I managed to solve this for me with a simple if/else block:
> List<ODataEntry> relatedEntries = null;
> if(oDataEntryProperties.get(propertyName) instanceof ODataEntry){
> relatedEntries = new ArrayList<ODataEntry>();
>
> relatedEntries.add((ODataEntry)oDataEntryProperties.get(propertyName));
> } else {
> relatedEntries =
> (List<ODataEntry>)oDataEntryProperties.get(propertyName);
> }
> The code is from the 1.1.0-SNAPSHOT master branch HEAD.
> I hope that helps.
--
This message was sent by Atlassian JIRA
(v6.1#6144)