Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data REST Joined Inheritance Issue

I have a Spring Data Repository over a single JPA entity. This entity is subclassed via joined inheritance.

Spring Data REST seems to have a problem interpreting this structure, at least automatically. Or maybe I'm misunderstanding the usage of Inheritance.JOINED

Any request for any entity with an Event returns the following:

{
    cause: null,
    message: "Cannot create self link for class com.foo.event.SubEvent! No persistent entity found!"
}

Maybe I'm asking too much for this project to know how to handle this, but is there a workaround that would group all of my Events under the same /events? Maybe even allowing me to filter on type?

I've left the basics of the application structure below.

Event.java

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({
  @Type(value = SubEvent.class), 
  ...
})
...
public class Event {
    @Id
    private long id;
    ...
}

SubEvent.java

@Entity
public class SubEvent extends Event {
    private String code;
    ...
}

EventRepository.java

@RepositoryRestResource(path = "events")
public interface EventRepository extends PagingAndSortingRepository<Event, Long> {
    ...    
}
like image 273
bvulaj Avatar asked Aug 22 '14 16:08

bvulaj


2 Answers

I think you're missing using Discriminator to let JPA understand what subclass to use for a given object (how does it know otherwise?).

I tend to use abstract classes for table-per-subclass hireachies, so here's an example adapted to that for you:

Event.java

@Entity
@DiscriminatorColumn(name = "type")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Event {
    @Id
    @GeneratedValue
    public Long id;

    public String type;
}

SubEvent.java

@Entity
@DiscriminatorValue("subevent")
@PrimaryKeyJoinColumn(name = "event_id")
public class PeeringService extends Service {
    private String code;
}

With the above code, you'll notice something odd however - when generating the resource path for one of these objects, it assumes you have a Repository for each subclass, and generates something like this:

{
  "type" : "subevent",
  "code" : "bacon",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8081/subEvents/1"
    },
    "peeringService" : {
      "href" : "http://localhost:8081/subEvents/1"
    }
  }
}

This is pretty easy to fix though, you just need to add the following annotation to your base class:

@RestResource(path = "events")

And it will generate the resource paths you'd expect!

Hope this helps :)

like image 120
bly Avatar answered Nov 17 '22 20:11

bly


I tried you classes out in a simple spring boot project nd they didn't give me any problems and I couldn't reproduce the issue you are having. However, search on the error message you describe gives a couple of posts that suggest that you need to create a SubEvent repository even f you don't use it, and that the problem arises in more complicated projects, such as using REST.

Reference: Cannot create self link for class X. No persistent entity found.

How to choose MappingContext in spring-data-jpa (2x) + spring-rest-webmvc?

So, try adding a SubEvent repository:

interface SubEventRepository extends CrudRepository<SubEvent, Long> {
}
like image 34
K.Nicholas Avatar answered Nov 17 '22 18:11

K.Nicholas