0

I use jquery.get() to make a call to the Spring-Boot backend, like this:

    var url = "http://localhost:8080/api/v1/get_holdings?userId=1"; 
    $.get(url, function(payload,status) {       
        if (status == "success") {
            $.each(payload.data, function (key,entry) {
              ...
            })
        }
        else {...

In SpringBoot I create a model that has an embedded model. In this case the model is called Holding and the embedded model is called Account, like this:

@Entity
@Table(name="holding")
public class Holding {
...
    @ManyToOne  //Many holdings to One Account
    @JoinColumn(name="account_id", nullable=false)
    private Account account;
...
//getters and setters...

The call to the database returns the data correctly. Then I try to return it to the jquery ajax call like this:

JsonResponse response = new JsonResponse();
List<Holding> holdings = holdingRepo.getUserHoldings(userId);
response.setData(holdings); //response looks correct but browser shows a 500 error.  Why?
return response;

JsonResponse is just a wrapper that I use for all my responses. I've used it many times and has worked fine for many other calls:

    public class JsonResponse {
        private String status = null;
        private Object data = null;
        //getters and setters...

It returns to the browser ok, but the browser gives a 500 error.

There are two ways that I can get the browser to accept the data.

  1. create a separate model that contains just the data I need with no embedded models
  2. create the json manually using the toString() method (pain in the butt)

I've tried converting the Holding object to JSON using Gson.toJson and JSONArray(holdings) but both of those methods fail. What am I missing?

user3217883
  • 1,216
  • 4
  • 38
  • 65
  • Show us what exception you see in your back end. – mentallurg May 30 '21 at 21:43
  • That's part of the problem. I watch the debugger line by line all the way to "return response" and no errors show. – user3217883 May 30 '21 at 23:03
  • 1) Don't you see any exceptions in the log? 2) If you see no exception in the log, set a breakpoint to catch all exceptions. – mentallurg May 31 '21 at 10:36
  • No, no exceptions in the log either. I set a breakpoint on the "return response" line. I right-clicked on it and looked at "breakpoint properties" but did not see anything called "catch all exceptions. I'll try out your solution next. Thank you. – user3217883 May 31 '21 at 16:27
  • * I set a breakpoint on the "return response" line* - No. I mean set breakpoint to "any exception". There must be an exception that is caught and converted to the status HTTP 500. – mentallurg May 31 '21 at 19:55

1 Answers1

0

You are using a relation. I suppose there happens an exception, like following:

org.hibernate.LazyInitializationException: could not initialize proxy

This can happen because Hibernate tries to optimize performance and does not load objects in the relation.

Then there are many answers to this question on SO.

  1. One solution can be to force Hibernate to initialize the proxy via
Hibernate.initialize( entity )
  1. Another approach can be not to send entities to the client, but to transform them into data transfer objects. If you do such transformation within the transaction, Hibernate will resolve all needed objects automatically and you will not need any tricks.
mentallurg
  • 4,967
  • 5
  • 28
  • 36
  • I read up on DTOs here: https://thorben-janssen.com/dto-projections/. DTOs are essentially the same thing I'm already doing with the new class I create to hold only the data I need. Both require a new class, which is extra work I shouldn't have to do. The Tuple method he describes sounds a little more promising in that it doesn't require a new class. Still, it should be a simple matter to convert the entity returned by the database to JSON. I don't understand why that does not seem to be possible. Anyway, I'll look into your approach #1 next. – user3217883 May 31 '21 at 17:19
  • After reading your description of Option #1 again, I realize that hibernate IS loading all the objects. When I look at the Holding objects returned by the database, they are all there, including the embedded Account object. – user3217883 May 31 '21 at 17:23
  • It depends on *when* you look at it. If you look at it *before* transaction completed, i.e. within a method marked as *transactional*, Hibernate will resolve proxy objects and will load real objects. If you check it *after* transaction was committed, then you see the reality. If then you see no proxies, then my assumption about Hibernate proxies was not correct. – mentallurg May 31 '21 at 19:58
  • Since its still early in development, I'm not using transactions yet. – user3217883 Jun 01 '21 at 18:58
  • It cannot be that you don't use transactions. You cannot use Hibernate session or entity manager, if there is no session. If you have not marked methods as transactional it does not mean they are not. E.g. the default simple implementation of Spring Data repository is transactional. – mentallurg Jun 02 '21 at 00:42