Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Jun 26 2017 20:07
    @remmeier banned @hibaymj
Remo
@remmeier
@avbitla HttpRequestContextAware gives low-level HTTP access
@wulfcolin I think in the meantime the nesting can be considered fairly stable. So that experimental could be removed IMHO. As for reasoning. As for reason, it is not uncommon for objects to have a parent and share the same lifecycle. So deleting the parent will delete them. The nesting helps to give "nice urls". Otherwise it behaves pretty much like any other repositories. You can even have it both ways, with nested urls but also direct non-nested access.
1 reply
Sebastian Wyrazik
@swyrazik
@remmeier Thanks for the info!
Rehab Reda
@rehab-reda0
Hi @remmeier
I have a question If I am having an id in the database it looks like #profile:{uuid}
I want it when it appears in json to be the {uuid} only How I can do that ?
Remo
@remmeier
simplest way might be to define an object representing that primary key. there is then a jackson annotation that specifies an object can be serialized to a string with a given serializer. dont remember its name just now, but crnk will pick this up. if not, let me know.
duncanportelli
@duncanportelli

Hi @remmeier. In a relationship where the source and target are both of the same type, while filtering/sorting/pagination how do you refer to just the target only since in a filter you are to specify the type.

E.g. a resource of a type person having a relationship "children" which is of type person as well. How can I get the persons together with the eldest child younger than 18?

/persons?include=children?filter[children][age][LT]=18&sort=-children.age&page[limit]=1

Anders Swanson
@anderskswanson
Hi, is there a public way to serialize/deserialize objects such that you get their JSON:API representation? I would like to do some processing on this representation without receiving it from an HTTP response (instead, directly from CRNK)
Essentially I would like to use the serializer that CRNK uses when it is creating an HTTP response.
Anders Swanson
@anderskswanson
Does CRNK use any filter to do this that I could intercept?
duncanportelli
@duncanportelli
@anderskswanson you can set your own serializer in CrnkBoot
Anders Swanson
@anderskswanson
@duncanportelli I've found AbstractDocumentFilter as an entry point here. This class contains a filter method which lets you access the JSON:API Response object.
I believe this fits my use case of intercepting the JSON:API response to do some processing on it :)
Remo
@remmeier
@duncanportelli if it has the same type, rhen as yet not possible. one could imagine swutching types with attribute paths. both approaches have there merits.
This message was deleted
Remo
@remmeier
@anderskswanson DocumentMapper gives you a Document object that can be serialized with Jackson or the DocumentFilter as mentioned if you want to intercept a live request
Rehab Reda
@rehab-reda0

Hi @remmeier I want to remove the foreign key constraint but to keep the relation between objects but without having a constraint
so If we have a parent object which has a list of childs
I want to easily link a non existent parent to a child object

this is can be done using jpa only in spring boot using this annotation @org.hibernate.annotations.ForeignKey(name = "none") but with crnk it returns like this when doing a post

  "errors": [
    {
      "status": "404",
      "code": "NOT_FOUND",
      "detail": "type=parent, ids=[2972b858-8f77-4462-89bb-7a406e248f46]",
      "source": {
        "pointer": ""
      },
      "meta": {
        "type": "NOT_FOUND",
        "resourceType": "child"
      }
    }
  ]
}

Parent class


@Data
@JsonApiResource(type = "parent", resourcePath = "parents")
@Entity
@Table(name = "parents")
public class Parent   {

  @Id
  @JsonApiId
  private UUID id;

  private String name;
  @JsonApiRelation(opposite = "parent",
      lookUp = LookupIncludeBehavior.AUTOMATICALLY_WHEN_NULL,
      repositoryBehavior = RelationshipRepositoryBehavior.FORWARD_OPPOSITE)
  @OneToMany(mappedBy = "parent")
  @org.hibernate.annotations.ForeignKey(name = "none")
  private List<Child> childs;
}

Child Class

@Data
@JsonApiResource(type = "child", resourcePath = "childs")
@Entity
@Table(name = "childs")
public class Child  {

  @Id
  @JsonApiId
  @GeneratedValue(generator = "UUID")
  @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
  @Column(name = "id", updatable = false, nullable = false)
  private UUID id;

  @JsonApiRelationId
  @Column(name = "parent_id")
  private UUID parentId;


  private String type;

  @JsonApiRelation(idField = "parentId", opposite = "childs",
      lookUp = LookupIncludeBehavior.AUTOMATICALLY_WHEN_NULL,
      repositoryBehavior = RelationshipRepositoryBehavior.FORWARD_OWNER,
      serialize = SerializeType.EAGER)
  @ManyToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "parent_id", insertable = false, updatable = false)
  @org.hibernate.annotations.ForeignKey(name = "none")
  private Parent parent;
public void setParentId(UUID parentId) {
    this.parentId = parentId;
    this.parent = null;
  }

  public void setParent(Parent parent) {
    this.parent = parent;
    this.parentId = parent != null ? parent.getId() : null;
  }}
Sarang Kanabargi
@SarangKanabargi
How are complex services implemented using crnk? in a typical web app all these features would get implemented in the service class. Will be great if you can give a github repo that implements business logic in a service class while using crnk
Roy
@depzor
Anyone familiar with the jpa n+1 issue? And how to prevent this with crnk?
Remo
@remmeier
@depzor question is, do you have one? Because crnk actually does quite a number of things to prevent them in the first place.
@rehab-reda0 Not the first time the topic has come up. As of yet there is no flag to ignore missing relationships. It will result in an error. Maybe @JsonApiRelation should allow to relax it. But generally not too fond of using it. An alternative approach could be if the parent repository returns a place holder with a status "DELETED" or something like that. Maybe could also be a visable option.
Remo
@remmeier
@SarangKanabargi there is an architecture chapter in the docs: http://www.crnk.io/releases/stable/documentation/#_architecture. Short answer is to model the business as a resource model. It requires a bit a different kind of thinking, but the end result can be a cleaner API.
Roy
@depzor
@remmeier yes I am experiencing multiple n+1 issues. Sometimes even more than > 100 queries are executed.
I know this can be solved by using JPA Entity graphs, but no clue how to integrate this with CRNK
Remo
@remmeier
you need to check where it is happening. Maybe there is an EAGER relation or something like that. crnk on its own should not have n+1 issues (graph loading and stuff is all taken care of).
Roy
@depzor
All marked as LAZY. I am using an older version of crnk: 2.11. Does that matter?
Roy
@depzor
I do use the "include" query parameter
Remo
@remmeier
Just now not aware of an issue. But 2.11 is really old and it should be a more or less smoth upgrade path. The one thing that did change in the meantime is a larger relationship handling refactoring. e.g. the JpaRelationshipRepository (or something like that) does not exist anymore. So things got (much) simpler. But a profiler or something should tell you where the loading happens. Generally crnk will be the one processing the "include", not JPA. So you would get a query for every inclusion. But not 1+n, rather 1+1
Roy
@depzor
Found the problem. we are using mapstruct to map entity to dto's, seems that during this mapping operation it triggers new queries to fetch some data
Remo
@remmeier
there is the possibility to customize the JpaEntityRepisitory to do Jpa graph loading. at least for newer version. but it is a bit undsr the hood
per default it will not load the entity graph in jpa, as it this can be a shource of trouble in many more complex scenarios.
Roy
@depzor
@Override
protected boolean fetchRelations() {
return true;
}
:)
this seems to activate it
duncanportelli
@duncanportelli
I am building a custom HttpStatusBehavior to return a custom Http Status code based on the type of the resource which I am reading from HttpStatusContext in getStatus(). When sending a DELETE request the ResponseDocument in HttpStatusContext is null since no data is returned in the response. How do you suggest getting the type of the resource then please?
Remo
@remmeier
maybe would be useful for the passed context to give access to QueryContext.
would be a little PR
Roy
@depzor
Is there any limitation for including 3rd level resources when fetchRelations is enabled? Getting a JPA error: "Unable to locate Attribute with the the given name ..."
Roy
@depzor
Ah issue seems to be fixed since version 3 in EntityGraphBuilderImpl :)
Roy
@depzor
One other question, when I enable entity graph within crnk by setting fetchRelations to true and I pass a OneToMany relation through the include query parameter
this makes the collection type also part of the entity graph which is really bad for performance (HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!)
Is there anyway to trigger a subselect query for collection types? So kind of a hybrid solution using entity graphs for one-to-one and many-to-one relationships and for collections a new sub select query?
Remo
@remmeier
are those nested objects crnk resources as well?
Roy
@depzor
yes all crnk resources
but all fetchPaths are passed through the EntityGraphBuilderImpl
Steve Brush
@brushs
@remmeier could you outline one of the use cases adding a TransactionRunner such as SpringTransactionRunner to a CRNK server instance solves? I understand the benefit if multiple actions are being performed behind a single call, however my understanding is only a single CRUD operation should be occurring. Is this for supporting multiple operation scenarios? Or are the single operations not as simple as they seem?
Remo
@remmeier
all crnk resources sounds perfect, because then you may not need any of it. dont populate relationships in mapstruct. at least not-loaded ones. crnk will then construct the graph.
Remo
@remmeier
I dont like the answer, but general graph loading in JPA/Hibernate is sh*t. not sure about most recent versions. Usually things explode in doing too much in a single query and limited options to prevent it or giving weird behavior. in crnk the graph loading is more robust and also accounts for things like security. for that reason never tried to go much further in jpa. one crnk limtation as of yet, it will assemble the graph in the response,.not the mapstruct.objects. sometimes the later would also be desirable.
transaction runner has different use cases. if the create/update/delete is more complex spanning multiple queries. operationsmodule supporting bulk mutation. and if desired database isolation when doing multiple reads/graph loading. for the later read committed is a frequent default, so not much impacf here.
Roy
@depzor
Thanks for pointing me into the right direction. I found a major problem in my code... well due Lombok..
using @data notation on my entity's

this creates a hashCode method for all properties and this triggers many lazy load queries when it creates a TupleElement at a certain point:

TupleElement(Object[] data) {
this.data = data;
this.hashCode = Arrays.hashCode(data);
}

Steve Brush
@brushs
thanks @remmeier -- is there an example available of a scenario with create/update/delete with multiple queries?
Roy
@depzor
Remo, I understand I dont need to populate relationships to the DTO to prevent new queries. However when I try to PATCH a relation it fails, because the relation isn't mapped into the dto.. why isnt the entity used here