[ 
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)

Reply via email to