Reputation: 15
This is a simplified example of the problem I'm having with Spring-Roo 2.0 returning JSON from the RESTful web-service call. Below are the Roo script for 2 classes (company, and user), the database content showing that the user is related to company_id=1, and the JSON I get back for the GET on the user. Note that company=null. That's the problem. Am I doing something wrong?
Roo Script
jpa setup --provider HIBERNATE --database MYSQL
--userName pivot --password pivot --databaseName testdb
entity jpa --class ~.model.MyUser
field string --fieldName firstName --notNull
field string --fieldName lastName --notNull
entity jpa --class ~.model.Company
field string --fieldName name –notNull
field set --fieldName users --type ~.model.MyUser --cardinality ONE_TO_MANY
--mappedBy company --comment "Users" --notNull false
repository jpa --all --package ~.repository
service --all --apiPackage ~.service.api --implPackage ~.service.impl
web mvc setup
/* ThymeLeaf view layer */
web mvc view setup --type THYMELEAF
web mvc templates setup --type THYMELEAF
web mvc controller --all --package ~.web --responseType THYMELEAF
/* JSON Rest controllers */
web mvc controller --all --responseType JSON --pathPrefix /json
web mvc finder --all --responseType THYMELEAF
web mvc finder --all --responseType JSON
Database
mysql> select * from my_user;
+----+------------+-----------+---------+------------+
| id | first_name | last_name | version | company_id |
+----+------------+-----------+---------+------------+
| 1 | First | Last | 0 | 1 |
+----+------------+-----------+---------+------------+
1 row in set (0.00 sec)
JSON
{
"content": [
{
"id": 1,
"version": 0,
"firstName": "First",
"lastName": "Last",
"company": null
}
],
"last": true,
"totalPages": 1,
"totalElements": 1,
"size": 20,
"number": 0,
"first": true,
"numberOfElements": 1,
"sort": null
}
Upvotes: 1
Views: 271
Reputation: 3882
The relationships generated by Spring Roo 2.0 are setted as Lazy by default to prevent data overload. Remember that Spring Roo tries to apply the best practises as possible. You could see this in your MyUser.java
entity:
@ManyToOne(fetch = FetchType.LAZY)
@EntityFormat
private Company company;
So, when you are obtaining all the records of MyUser
entity, the relationships with Comapny are not loaded by default.
However, If you know that you want to obtain this information, you should customize the generated code by Spring Roo. Follow these steps:
Make push-in of the method findAll
declared in theMyUserRepositoryImpl
class. To do it, execute the following command:
push-in --class ~.repository.MyUserRepositoryImpl --method findAll(GlobalSearch,Pageable)
After that, open the MyUserRepositoryImpl.java
class and change the default query to execute a left join with Company
. To do that, change this generated code:
JPQLQuery<MyUser> query = from(myUser);
to this one:
JPQLQuery<MyUser> query = from(myUser).leftJoin(myUser.company).fetchJoin();
Repeat the process with the findOne
method that is used when you try to obtain an individual item instead of a list. In this case, you should define the findOne
method in the MyUserRepositoryCustom
interface and after that, implement it using QueryDSL in MyUserRepositoryImpl
.
With the changes above, you should be able to obtain the following JSON when you acces to the url http://localhost:8080/json/myusers/
using GET
operation:
{
"content": [
{
"id": 1,
"version": 0,
"firstName": "test",
"lastName": "test",
"company": {
"id": 1,
"version": 0,
"name": "aaa"
}
}
],
"last": true,
"totalPages": 1,
"totalElements": 1,
"sort": null,
"numberOfElements": 1,
"first": true,
"size": 20,
"number": 0
}
As an advice, I have to say that you should be careful when you use entities with relationships in JSON responses. Maybe you could get a cyclic relationship if some entity is related with other entity that is related with the first one. Instead of return the complete entity in your JSON responses, you should return an entity projection that only shows the identifier of the related element instead of the entire related entity.
Hope it helps,
Upvotes: 2