Implementation of a JSON:API server in Java using JAX-RS, Bean Validation, and Java Persistence (JPA). This library is under active development and APIs may not be stable. Please open issues for feature requests or bug reports.
- Simplify configuration, minimize custom interfaces/classes in client application code
- API end point generates JavaScript client module and entities
- Align client interface with JPA
EntityManager
Replace VERSION
with the latest from Maven Central:
<dependency>
<groupId>io.xlate</groupId>
<artifactId>jsonapi-rvp</artifactId>
<version>VERSION</version>
</dependency>
@Path("/blogapi")
@Transactional // when using JTA transactions
public class BlogResources extends JsonApiResource {
@PostConstruct
void configure() {
Set<JsonApiResourceType<?>> resourceTypes = new HashSet<>();
resourceTypes.add(JsonApiResourceType.define("posts", Post.class)
.build());
resourceTypes.add(JsonApiResourceType.define("comments", Comment.class)
.build());
super.initialize(resourceTypes);
}
}
@Entity
@Table(name = "POSTS")
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column
private String title;
@Column
private String text;
@OneToMany(mappedBy = "post")
private List<Comment> comments;
// ... Getters and Setters
}
@Entity
@Table(name = "COMMENTS")
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column
private String text;
@ManyToOne
@JoinColumn(name = "post_id")
private Post post;
// ... Getters and Setters
}
Assuming a server on localhost, port 8080, JSON:API models are now available at http://localhost:8080/blogapi/{resource-type}
. See the JSON:API specification for URL conventions and message body formatting. Additionally, an ES6 client module for the API can be retrieved at http://localhost:8080/blogapi/client.js
. The ES6 client utilizes the standard fetch
API available in modern browsers.
GET /blogapi/posts/2?include=comments HTTP/1.1
Accept: application/vnd.api+json
{
"jsonapi":{"version":"1.0"},
"data":{
"id": "2",
"type": "posts",
"attributes": {
"title": "Title Two",
"text": "Text two."
},
"relationships": {
"comments": {
"links": {
"self": "/test/posts/2/relationships/comments",
"related": "/test/posts/2/comments"
},
"data": [{
"type": "comments", "id": "2"
}]
},
"author": {
"links": {
"self": "/test/posts/2/relationships/author",
"related": "/test/posts/2/author"
},
"data": null
}
},
"links": {
"self": "/test/posts/2"
}
},
"included": [{
"type": "comments",
"id": "2",
"attributes": {
"text": "Comment two."
},
"relationships": {
"post": {
"links": {
"self": "/test/comments/2/relationships/post",
"related": "/test/comments/2/post"
}
}
},
"links": {
"self": "/test/comments/2"
}
}]
}