crnk-project / crnk-framework

JSON API library for Java
Apache License 2.0
287 stars 153 forks source link

Included collection #474

Open jevanlingen opened 5 years ago

jevanlingen commented 5 years ago

Sideloading Collections seems not to work very well; I am using version 2.6.20180430102904. I got following model:

@JsonApiResource(type="tenants")
public class Tenant {
  @JsonApiId
  private long id;
  // other props

  @JsonApiRelation
  private Shard shard;
  @JsonApiRelation
  private Customer customer;
  @JsonApiRelation(opposite="tenant")
  private Set<ApplicationLink> applicationLinks; // links can be extended by a subtype
}

If I want to sideload both the shard and customer, I would call /api/tenants?include[tenants]=shard,customer. It returns expected data:

{
  "data": [
    {
      "id": "5",
      "type": "tenants",
      "attributes": { ... }
      },
      "relationships": {
        "applicationLinks": {
          "links": { ... }
        },
        "shard": {
          "data": {
            "id": "1",
            "type": "shards"
          }
        },
        "customer": {
          "data": {
            "id": "1",
            "type": "customers"
          }
        }
      }
    }
  ],
  "included": [
    {
      "id": "1",
      "type": "customers",
      "attributes": { ... }
    },
    {
      "id": "1",
      "type": "shards",
      "attributes": { ... }
    }
  ]
}

Now, would I sideload the applicationLinks by calling /api/tenants?include[tenants]=applicationLink, I stumble upon following error:

io.crnk.core.exception.InternalServerErrorException: null
  at io.crnk.core.engine.internal.http.JsonApiRequestProcessor.toErrorResponse(JsonApiRequestProcessor.java:180) [crnk-core-2.6.20180430102904.jar:na]
  at io.crnk.core.engine.internal.http.JsonApiRequestProcessor.processAsync(JsonApiRequestProcessor.java:163) [crnk-core-2.6.20180430102904.jar:na]
  at io.crnk.core.engine.internal.http.JsonApiRequestProcessor.processAsync(JsonApiRequestProcessor.java:124) [crnk-core-2.6.20180430102904.jar:na]
  at io.crnk.core.engine.internal.http.HttpRequestDispatcherImpl.process(HttpRequestDispatcherImpl.java:71) [crnk-core-2.6.20180430102904.jar:na]
  at io.crnk.spring.SpringCrnkFilter.doFilter(SpringCrnkFilter.java:51) [crnk-setup-spring-boot1-2.6.20180430102904.jar:na]

But when I use a filter, like /api/tenants?filter[tenants][prop][EQ]=someValueOfProp&include[tenants]=applicationLink, I get some data back:

{
  "data": [
    {
      "id": "5",
      "type": "tenants",
      "attributes": { ... }
      },
      "relationships": {
        "applicationLinks": {
          "data": [
            {
              "id": "1",
              "type": "app-links-type-one"
            },
            {
              "id": "3",
              "type": "app-links-type-two"
            }
          ]
        },
        "shard": {
          "data": null,
          "links": { ... }
        },
        "customer": {
          "data": null,
          "links": { ... }
        }
      }
    }
  ],
  "included": [
    {
      "id": "3",
      "type": "app-links-type-one"
      "attributes": { ... }
    },
    {
      "id": "1",
      "type": "app-links-type-two",
      "attributes": { ... }
    }
  ]
}

Sadly this data is wrong, because the customer and shard relationships has turned to null.

And, last but not least, should I want to sideload shard and applicationLink both, by using /api/tenants?filter[tenants][prop][EQ]=someValueOfProp&include[tenants]=shard,applicationLink, the shard relationship is not sideloaded at all. With other words, &include[tenants]=applicationLink or &include[tenants]=shard,applicationLink do return the same data.

remmeier commented 5 years ago

Hi, I cannot directly say what is wrong. In general the inclusion mechanism is very reliable also for much more complex use cases than here.

jevanlingen commented 5 years ago

I just updated to 2.11.20190113153635; I was not aware the current builds are no longer published to the Maven Repository.

So, to answer your questions:

Do you have the full exception? I do, but by updating to 2.11 the stacktrace does show the Caused By now. It throws a could not initialize proxy - no Session error. So the error has nothing to do with Crnk (but by updating, the cause has been revealed).

As said before, by using a different call like /api/tenants?filter[tenants][prop][EQ]=someValueOfProp&include[tenants]=applicationLinks, I do get data back. Clearly be providing extra filters, the set is already loaded so the could not initialize proxy - no Session disappears.

Do note though, the result is still the same as written in above's question. Sadly, by updating Crnk the behavior did not change, it's still broken!

LookupIncludeBehavior is set as desired? Yes, it is. The shard and customer relationships can either be null or filled, so the default behavior suits this case very well.

remmeier commented 5 years ago

yes, maven central has proven to be rather unreliable. It works for single artifacts, but publishing the entire project did not work rather frequently.

You seem have a lazy-loading issue, maybe rather related due to a configuration issue than an actual bug. During serialization the transaction has already finished and it is not possible to do further loading (if you use crnk-jpa for example). And it probably should not do that in the first place as it will ruin performance. How does your setup look like? Do you make use of crnk-jpa with dto mapping? have something custom?

We should try to get:

/api/tenants?include[tenants]=applicationLink

working. There are two choices: let crnk do the relationship loading to avoid that lazy-loaded collections alltogether or have the collections initialized by the repository.

winne42 commented 3 years ago

@jevanlingen Any updates on this issue? Can the issue be closed?