javaspring-bootodataolingo

Doing a post on spring boot olingo on an entity with a relationship


I have some odata V2 apis built from spring-boot and olingo. I'm trying to a post to an entity with a relationship

public class CompanyProfileDetail {

    private Long id;

    @NotNull
    private Long version;

    @NotNull
    @OneToOne
    @JoinColumn(name = "company_profile_id", referencedColumnName = "id")
    private CompanyProfile companyProfile;
...
}

public class CompanyProfile {

    private Long id;
    
    @NotNull
    private Long version;

...
}

So when I try to post this using the CompanyProfileDetails api

{
    "Version": "1",
    "CompanyProfile": "1"
}

it doesn't work but this

{
    "Version": "1",
    "CompanyProfileDetails" : {
        "__metadata": {
                "id": "http://localhost:8080/odata/CompanyProfiles(1L)",
                "uri": "http://localhost:8080/odata/CompanyProfiles(1L)",
                "type": "default.CompanyProfile"
            }
    }
}

works. So now I'm wondering if this is an odata standard of posting with relationships or is there some setting that will accept the first structure.

FYI the "CompanyProfileDetails" in the second data structure is how olingo automatically names the related entity. It's actually the CompanyProfiles entity

As another example:

public class CompanyProfile {

    private Long id;
    
    @NotNull
    private Long version;

    @ManyToOne
    @JoinColumn(name = "address", referencedColumnName = "id")
    private Location address;

    @Column(name="contact_number")
    private String contactNumber;

    @NotNull
    @Column(name="name")
    private String name;

    @NotNull
    @Column(name="status")
    private String status;
...
}

public class Location {
    
    @Id
    @Column(name = "id")
    @NotNull
    private Long id;


    private Long version;

    @ManyToOne
    @JoinColumn(name = "city", referencedColumnName = "id")
    private CityMunicipality city;

    @ManyToOne
    @JoinColumn(name = "province", referencedColumnName = "id")
    private Province province;
}

The working request looks like this:

{
    "Version": "1",
    "ContactNumber": "1245",
    "Name": "OIL Tycoon corporation",
    "Status": "OK",
    "LocationDetails" : {
        "__metadata": {
                "id": "http://localhost:8080/odata/Locations(2L)",
                "uri": "http://localhost:8080/odata/Locations(2L)",
                "type": "default.Location"
            }
    }
}

However this does not work:

{
    "Version": "1",
    "ContactNumber": "1245",
    "Name": "OIL Tycoon corporation",
    "Status": "OK",
    "Address" : "2",
}

Location with an Id of 2 exists in this case.

As requested the $metadata. This is for the second example. Hope this helps!

<EntityType Name="CompanyProfile">
                <Key>
                    <PropertyRef Name="Id"></PropertyRef>
                </Key>
                <Property Name="Address" Type="Edm.Int64" Nullable="true"></Property>
                <Property Name="ContactNumber" Type="Edm.String" Nullable="true" MaxLength="255"></Property>
                <Property Name="Id" Type="Edm.Int64" Nullable="false"></Property>
                <Property Name="Version" Type="Edm.Int64"></Property>
                <Property Name="Name" Type="Edm.String"></Property>
                <NavigationProperty Name="LocationDetails" Relationship="default.CompanyProfile_Location_Many_ZeroToOne0" FromRole="CompanyProfile" ToRole="Location"></NavigationProperty>
</EntityType>
<EntityType Name="Location">
                <Key>
                    <PropertyRef Name="Id"></PropertyRef>
                </Key>
                <Property Name="City" Type="Edm.String" Nullable="true"></Property>
                <Property Name="Id" Type="Edm.Int64" Nullable="false"></Property>
                <Property Name="Province" Type="Edm.String" Nullable="true"></Property>
                <Property Name="Region" Type="Edm.Region" Nullable="true"></Property>
                <Property Name="Version" Type="Edm.Int64" Nullable="true"></Property>
</EntityType> 

Solution

  • The Default Implementaion of Olingo 2.0 JPA processor names the Navigation properties in the format <Navigation Property Name>Details , so for example if you have a join named Location the navigation property will be named as LocationDetails

    To perform the DeepInset you can use the following payload

    {
        "version": "1",
        "contactNumber" : "",
        "LocationDetails": {
            "id":"",
            "version":"",
             "CityMunicipalityDetails":{
                 // all attributes of city class
              },
             "ProvinceDetails":{
                // all attributes of province class
              }
        
        }
    }
    

    Alternatively you can also look at the implementation of $batch in OData 2 as Deep inserts were part of Later Version of OData Implementations but Olingo 2.0 JPA Processor implemented in version 2.0 also.

    PS: Please check the $metadata for the navigation property names and if possible post the $metadata content if this solution doesn't solves the issue.