Carsten Milkau created OLINGO-1387:
--------------------------------------
Summary: olingo-odata2-annotation-processor: support multiple
links between the same entity sets
Key: OLINGO-1387
URL: https://issues.apache.org/jira/browse/OLINGO-1387
Project: Olingo
Issue Type: Improvement
Components: odata2-annotation
Reporter: Carsten Milkau
Fix For: V2 2.0.12, V2 2.1.0
Attachments: Car.java, Driver.java,
odata2-annotation-processor-multiple-links-rc1.patch
When multiple links (associations) exist between the same two entity sets, the
annotation processor does not distinguish between them, even if you name the
associations explicitly. The EDM provider binds the same association (whatever
it finds first) to all navigation properties between this pair of entity sets,
reading and writing relations/links produces the same data for each navigation
property, even if they should use different associations.
*Steps to reproduce:*
# Checkout cars-annotation-archetype
# Add property "previousDrivers" to entity type Car (see Car.java)
# Add property "previousCars" to entity type Driver (see Driver.java)
# Optional: explicitly name association for properties "Car.Driver" and
"Driver.Car"
# Run example service
# Retrieve EDMX metadata
*Expected results:*
Properties "previousDrivers" and "previousCars" use association
"Car_previousDrivers_2_Driver_previousCars":
{color:#0000ff}<{color}{color:#800000}EntityType{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Car">{color}
{color:#0000ff}<{color}{color:#800000}Key{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}PropertyRef{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Id"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}</{color}{color:#800000}Key{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Id"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.String"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Model"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.String"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Price"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.Double"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"ModelYear"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.Int32"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Updated"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.DateTime"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}NavigationProperty{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Manufacturer"{color}
{color:#ff0000}Relationship{color}{color:#000000}={color}{color:#0000ff}"MyFormula.r_Cars_2_r_Manufacturer"{color}
{color:#ff0000}FromRole{color}{color:#000000}={color}{color:#0000ff}"r_Cars"{color}
{color:#ff0000}ToRole{color}{color:#000000}={color}{color:#0000ff}"r_Manufacturer"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}NavigationProperty{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Driver"{color}
{color:#ff0000}Relationship{color}{color:#000000}={color}{color:#0000ff}"MyFormula.Car_currentDriver_2_Driver_currentCar"{color}
{color:#ff0000}FromRole{color}{color:#000000}={color}{color:#0000ff}"r_Car"{color}
{color:#ff0000}ToRole{color}{color:#000000}={color}{color:#0000ff}"r_Driver"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}NavigationProperty{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"PreviousDrivers"{color}
{color:#ff0000}Relationship{color}{color:#000000}={color}{color:#0000ff}"MyFormula.Car_previousDrivers_2_Driver_previousCars"{color}
{color:#ff0000}FromRole{color}{color:#000000}={color}{color:#0000ff}"r_PreviousCars"{color}
{color:#ff0000}ToRole{color}{color:#000000}={color}{color:#0000ff}"r_PreviousDrivers"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}</{color}{color:#800000}EntityType{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}EntityType{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Driver">{color}
{color:#0000ff}<{color}{color:#800000}Key{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}PropertyRef{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Id"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}</{color}{color:#800000}Key{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Id"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.Int64"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Name"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.String"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Lastname"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.String"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Nickname"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.String"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Birthday"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.DateTime"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}NavigationProperty{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Car"{color}
{color:#ff0000}Relationship{color}{color:#000000}={color}{color:#0000ff}"MyFormula.Car_currentDriver_2_Driver_currentCar"{color}
{color:#ff0000}FromRole{color}{color:#000000}={color}{color:#0000ff}"r_Driver"{color}
{color:#ff0000}ToRole{color}{color:#000000}={color}{color:#0000ff}"r_Car"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}NavigationProperty{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"PreviousCars"{color}
{color:#ff0000}Relationship{color}{color:#000000}={color}{color:#0000ff}"MyFormula.Car_previousDrivers_2_Driver_previousCars"{color}
{color:#ff0000}FromRole{color}{color:#000000}={color}{color:#0000ff}"r_PreviousDrivers"{color}
{color:#ff0000}ToRole{color}{color:#000000}={color}{color:#0000ff}"r_PreviousCars"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}</{color}{color:#800000}EntityType{color}{color:#0000ff}>{color}
*Actual results:*
Properties "previousDrivers" and "previousCars" use association
"Car_currentDriver_2_Driver_currentCar":
{color:#0000ff}<{color}{color:#800000}EntityType{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Car">{color}
{color:#0000ff}<{color}{color:#800000}Key{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}PropertyRef{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Id"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}</{color}{color:#800000}Key{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Id"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.String"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Model"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.String"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Price"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.Double"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"ModelYear"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.Int32"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Updated"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.DateTime"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}NavigationProperty{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Manufacturer"{color}
{color:#ff0000}Relationship{color}{color:#000000}={color}{color:#0000ff}"MyFormula.r_Cars_2_r_Manufacturer"{color}
{color:#ff0000}FromRole{color}{color:#000000}={color}{color:#0000ff}"r_Cars"{color}
{color:#ff0000}ToRole{color}{color:#000000}={color}{color:#0000ff}"r_Manufacturer"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}NavigationProperty{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Driver"{color}
{color:#ff0000}Relationship{color}{color:#000000}={color}{color:#0000ff}"MyFormula.Car_currentDriver_2_Driver_currentCar"{color}
{color:#ff0000}FromRole{color}{color:#000000}={color}{color:#0000ff}"r_Car"{color}
{color:#ff0000}ToRole{color}{color:#000000}={color}{color:#0000ff}"r_Driver"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}NavigationProperty{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"PreviousDrivers"{color}
{color:#ff0000}Relationship{color}{color:#000000}={color}{color:#0000ff}"MyFormula.Car_currentDriver_2_Driver_currentCar"{color}
{color:#ff0000}FromRole{color}{color:#000000}={color}{color:#0000ff}"r_Car"{color}
{color:#ff0000}ToRole{color}{color:#000000}={color}{color:#0000ff}"r_Driver"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}</{color}{color:#800000}EntityType{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}EntityType{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Driver">{color}
{color:#0000ff}<{color}{color:#800000}Key{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}PropertyRef{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Id"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}</{color}{color:#800000}Key{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Id"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.Int64"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Name"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.String"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Lastname"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.String"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Nickname"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.String"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}Property{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Birthday"{color}
{color:#ff0000}Type{color}{color:#000000}={color}{color:#0000ff}"Edm.DateTime"{color}
{color:#ff0000}Nullable{color}{color:#000000}={color}{color:#0000ff}"true"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}NavigationProperty{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"Car"{color}
{color:#ff0000}Relationship{color}{color:#000000}={color}{color:#0000ff}"MyFormula.Car_currentDriver_2_Driver_currentCar"{color}
{color:#ff0000}FromRole{color}{color:#000000}={color}{color:#0000ff}"r_Driver"{color}
{color:#ff0000}ToRole{color}{color:#000000}={color}{color:#0000ff}"r_Car"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}<{color}{color:#800000}NavigationProperty{color}
{color:#ff0000}Name{color}{color:#000000}={color}{color:#0000ff}"PreviousCars"{color}
{color:#ff0000}Relationship{color}{color:#000000}={color}{color:#0000ff}"MyFormula.Car_currentDriver_2_Driver_currentCar"{color}
{color:#ff0000}FromRole{color}{color:#000000}={color}{color:#0000ff}"r_Driver"{color}
{color:#ff0000}ToRole{color}{color:#000000}={color}{color:#0000ff}"r_Car"{color}{color:#800000}/{color}{color:#0000ff}>{color}
{color:#0000ff}</{color}{color:#800000}EntityType{color}{color:#0000ff}>{color}
*Workaround:*
# Only workaround is to change your model. You could promote the associations
to entity types only consisting of navigation properties, for instance.
*Additional information:*
# Interface Datasource lacks a means of communicating the link followed when
reading or writing related data. Only the target entity set can be
communicated. The fix must change this.
# The patch currently just adds an optional parameter to the relevant
interface methods passing the navigation property. When the parameter is not
passed, the navigation property is guessed as before. This breaks applications
that directly use the interface, but only those.
# Obviously, there is no point in both changing the interface and keeping the
old guessing behavior. But which of both is the correct choice?
## (Incompatible change) Change the relevant interface methods and pass the
necessary navigation property.
## (Compatible change) Make an extension interface with new methods that
additionally pass the navigation property and detect whether the extension
interface is supported by the Datasource implementation.
## Other: ___________________________
--
This message was sent by Atlassian Jira
(v8.3.2#803003)