JsonMappingException: could not initialize proxy - no Session
Asked Answered
D

6

24

I am building a RESTful Web Service that consumes and returns JSON. I am encountering the following stack trace when I try to fetch an ESRBRating object from the database through the service layer. However when I inject the Spring Data JPA repository directly to the controller and use that to fetch the ESRBRating by ID it works fine. However when calling through the service layer it does not work. I have provided the stack trace and code below. Can someone explain to me why this is happening when going through a service layer but not when going through the Spring Data JPA repository directly? How do I resolve this issue?

Stack Trace

Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
    at net.jkratz.igdb.model.ESRBRating_$$_jvst319_0.getId(ESRBRating_$$_jvst319_0.java)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:466)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:639)
    ... 76 more

Controller

@RestController
@RequestMapping(produces = "application/json", value="/esrbrating")
public class ESRBRatingController {

    @Inject
    ESRBRatingService esrbRatingService;

    @Inject
    ESRBRatingRepository esrbRatingRepository;

    private Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * Returns all ESRB ratings in database
     * 
     * @return List of ESRBRating objects
     * @see ESRBRating
     */
    @RequestMapping(value = {"","/"}, method = RequestMethod.GET)
    public ResponseEntity<List<ESRBRating>> getESRBRatings() {
        List<ESRBRating> esrbRatings = esrbRatingService.getESRBRatings();
        return new ResponseEntity<>(esrbRatings, HttpStatus.OK);
    }

    /**
     * Returns a single ESRB rating object if exists, otherwise returns HTTP status code 404
     *
     * @param id ID of the ESRB Rating
     * @return ESRB Rating when found
     * @see ESRBRating
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public ResponseEntity<?> getUser(@PathVariable("id") Long id) {
        logger.debug("Attempting to fetch ESRB rating with ID: {}", id);
        ESRBRating esrbRating = esrbRatingService.getESRBRating(id);
        //ESRBRating esrbRating = esrbRatingRepository.findOne(id);

        if (esrbRating == null) {
            return new ResponseEntity<>("ESRB Rating not found", HttpStatus.NOT_FOUND);
        } else {
            return new ResponseEntity<>(esrbRating, HttpStatus.OK);
        }
    }

}

Service

@Service
@Transactional
public class ESRBRatingServiceImpl implements ESRBRatingService {

    @Value("#{paging.games.maxPageSize}")
    private static int DEFAULT_PAGE_SIZE;

    @Value("#{paging.games.maxPageSize}")
    private static int MAX_PAGE_SIZE;

    @Inject
    private ESRBRatingRepository esrbRatingRepository;

    @Override
    public List<ESRBRating> getESRBRatings() {
        List<ESRBRating> ratings =  esrbRatingRepository.findAll();
        return ratings;
    }

    @Override
    public ESRBRating getESRBRating(Long id) {
        return esrbRatingRepository.getOne(id);
    }

    @Override
    public ESRBRating saveESRBRating(ESRBRating esrbRating) {
        return esrbRatingRepository.saveAndFlush(esrbRating);
    }

    @Override
    public boolean deleteESRBRating(Long id) {
        esrbRatingRepository.delete(id);
        return true;
    }
}

Repository

package net.jkratz.igdb.repository;

import net.jkratz.igdb.model.ESRBRating;

import org.springframework.data.jpa.repository.JpaRepository;

public interface ESRBRatingRepository extends JpaRepository<ESRBRating, Long> {

}

Model

@Entity
@Table(name = "esrb_rating", schema = "igdb")
@JsonIgnoreProperties(ignoreUnknown = true)
public class ESRBRating implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @NotNull
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    private Long id;

    @NotNull
    @Size(min = 1, max = 255)
    @Column(name = "title", nullable = false, length = 255)
    private String title;

    @Size(max = 65535)
    @Column(length = 65535)
    private String description;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "esrbRating")
    private List<Game> games;

    public ESRBRating() {
    }

    public ESRBRating(Long id, String title, String description) {
        this.id = id;
        this.title = title;
        this.description = description;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ESRBRating that = (ESRBRating) o;

        return Objects.equal(this.id, that.id) &&
                Objects.equal(this.title, that.title) &&
                Objects.equal(this.description, that.description);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(id, title, description);
    }

    @Override
    public String toString() {
        return Objects.toStringHelper(this)
                .add("id", id)
                .add("title", title)
                .add("description", description)
                .toString();
    }
}

This controller code works fine, going through the repository directly.

@RestController
@RequestMapping(produces = "application/json", value="/esrbrating")
public class ESRBRatingController {

@Inject
ESRBRatingService esrbRatingService;

@Inject
ESRBRatingRepository esrbRatingRepository;

private Logger logger = LoggerFactory.getLogger(getClass());

/**
 * Returns all ESRB ratings in database
 * 
 * @return List of ESRBRating objects
 * @see ESRBRating
 */
@RequestMapping(value = {"","/"}, method = RequestMethod.GET)
public ResponseEntity<List<ESRBRating>> getESRBRatings() {
    List<ESRBRating> esrbRatings = esrbRatingService.getESRBRatings();
    return new ResponseEntity<>(esrbRatings, HttpStatus.OK);
}

/**
 * Returns a single ESRB rating object if exists, otherwise returns HTTP status code 404
 *
 * @param id ID of the ESRB Rating
 * @return ESRB Rating when found
 * @see ESRBRating
 */
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ResponseEntity<?> getUser(@PathVariable("id") Long id) {
    logger.debug("Attempting to fetch ESRB rating with ID: {}", id);
    ESRBRating esrbRating = esrbRatingRepository.findOne(id);

    if (esrbRating == null) {
        return new ResponseEntity<>("ESRB Rating not found", HttpStatus.NOT_FOUND);
    } else {
        return new ResponseEntity<>(esrbRating, HttpStatus.OK);
    }
}

}

UPDATE:

I followed Randall Harleigh advice and set the reverse collection with @JsonIgnore. However now I am getting an entirely different stack trace. It seems now Jackson / Spring doesn't know how to serialize ESRBRating. Any tips on this one?

org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: net.jkratz.igdb.model.ESRBRating_$$_jvstb5c_0["handler"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: net.jkratz.igdb.model.ESRBRating_$$_jvstb5c_0["handler"])
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:238)
    at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:158)
    at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:138)
    at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:155)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: net.jkratz.igdb.model.ESRBRating_$$_jvstb5c_0["handler"])
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:59)
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:26)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:505)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:639)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:114)
    at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:1887)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231)
    ... 72 more

Update 2:

I ended up putting @Proxy(lazy = false) on the ESRBRating class and now it works fine. However I'm curious what kind of performance impacts this could have?

@Entity
@Table(name = "esrb_rating", schema = "igdb")
@JsonIgnoreProperties(ignoreUnknown = false)
@Proxy(lazy = false)
public class ESRBRating implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @NotNull
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    private Long id;

    @NotNull
    @Size(min = 1, max = 255)
    @Column(name = "title", nullable = false, length = 255)
    private String title;

    @Size(max = 65535)
    @Column(length = 65535)
    private String description;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "esrbRating")
    private List<Game> games;

    public ESRBRating() {
    }

    public ESRBRating(Long id, String title, String description) {
        this.id = id;
        this.title = title;
        this.description = description;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }


    @JsonIgnore
    public List<Game> getGames() {
        return games;
    }

    public void setGames(List<Game> games) {
        this.games = games;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ESRBRating that = (ESRBRating) o;

        return Objects.equal(this.id, that.id) &&
                Objects.equal(this.title, that.title) &&
                Objects.equal(this.description, that.description);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(id, title, description);
    }

    @Override
    public String toString() {
        return Objects.toStringHelper(this)
                .add("id", id)
                .add("title", title)
                .add("description", description)
                .toString();
    }
}

As requested here is the Game class

@Entity
@Table(name = "game", schema = "igdb",
        indexes = {@Index(name = "idx_game_title", columnList = ("title"), unique = false),
                @Index(name = "idx_game_developer", columnList = ("developer"), unique = false),
                @Index(name = "idx_game_publisher", columnList = ("publisher"), unique = false)})
@JsonIgnoreProperties(ignoreUnknown = true)
public class Game implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @NotNull
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    private Long id;

    @NotNull
    @Size(min = 1, max = 255)
    @Column(name = "title", nullable = false, length = 255)
    private String title;

    @Size(max = 65535)
    @Column(name = "description", length = 65535)
    private String description;

    @Size(max = 255)
    @Column(name = "developer", length = 255)
    private String developer;

    @Size(max = 255)
    @Column(name = "publisher", length = 255)
    private String publisher;

    @NotNull
    @Size(max = 4)
    @Column(name = "players", nullable = false)
    private short players;

    @NotNull
    @Column(name = "cooperative", nullable = false)
    private boolean cooperative;

    @NotNull
    @Column(name = "release_date", nullable = false)
    @Temporal(TemporalType.DATE)
    private Date releaseDate;

    @Size(max = 255)
    @Column(name = "image", length = 255)
    private String image;

    @JoinColumn(name = "esrb_rating_id", referencedColumnName = "id", nullable = false)
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    private ESRBRating esrbRating;   

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "game")
    private List<GamePlatformMap> gamePlatformMap;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "game")
    private List<GameGenreMap> gameGenreMap;

    public Game() {

    }

    public Game(Long id, String title, String description, String developer,
            String publisher, short players, boolean cooperative,
            Date releaseDate, String image, ESRBRating esrbRating) {
        super();
        this.id = id;
        this.title = title;
        this.description = description;
        this.developer = developer;
        this.publisher = publisher;
        this.players = players;
        this.cooperative = cooperative;
        this.releaseDate = releaseDate;
        this.image = image;
        this.esrbRating = esrbRating;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDeveloper() {
        return developer;
    }

    public void setDeveloper(String developer) {
        this.developer = developer;
    }

    public String getPublisher() {
        return publisher;
    }

    public void setPublisher(String publisher) {
        this.publisher = publisher;
    }

    public short getPlayers() {
        return players;
    }

    public void setPlayers(short players) {
        this.players = players;
    }

    public boolean isCooperative() {
        return cooperative;
    }

    public void setCooperative(boolean cooperative) {
        this.cooperative = cooperative;
    }

    public Date getReleaseDate() {
        return releaseDate;
    }

    public void setReleaseDate(Date releaseDate) {
        this.releaseDate = releaseDate;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public ESRBRating getEsrbRating() {
        return esrbRating;
    }

    public void setEsrbRating(ESRBRating esrbRating) {
        this.esrbRating = esrbRating;
    }

    @JsonIgnore
    public List<GamePlatformMap> getGamePlatformMap() {
        return gamePlatformMap;
    }

    public void setGamePlatformMap(List<GamePlatformMap> gamePlatformMap) {
        this.gamePlatformMap = gamePlatformMap;
    }

    @JsonIgnore
    public List<GameGenreMap> getGameGenreMap() {
        return gameGenreMap;
    }

    public void setGameGenreMap(List<GameGenreMap> gameGenreMap) {
        this.gameGenreMap = gameGenreMap;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Game that = (Game) o;

        return Objects.equal(this.id, that.id) &&
                Objects.equal(this.title, that.title) &&
                Objects.equal(this.description, that.description) &&
                Objects.equal(this.developer, that.developer) &&
                Objects.equal(this.publisher, that.publisher) &&
                Objects.equal(this.players, that.players) &&
                Objects.equal(this.cooperative, that.cooperative) &&
                Objects.equal(this.releaseDate, that.releaseDate) &&
                Objects.equal(this.image, that.image) &&
                Objects.equal(this.esrbRating, that.esrbRating);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(id, title, description, developer, publisher, players,
                cooperative, releaseDate, image, esrbRating);
    }

    @Override
    public String toString() {
        return Objects.toStringHelper(this)
                .add("id", id)
                .add("title", title)
                .add("description", description)
                .add("developer", developer)
                .add("publisher", publisher)
                .add("players", players)
                .add("cooperative", cooperative)
                .add("releaseDate", releaseDate)
                .add("image", image)
                .add("esrbRating", esrbRating)
                .toString();
    }
}
Dampen answered 16/11, 2014 at 13:36 Comment(3)
@Proxy(lazy = false) this save my day thanks.Italicize
@ André Luís Tomaz Dionisio - Thanks! your suggestion does the job :)Bouley
Similar to #21708839Bluff
T
47

This typically happens when you are returning an object via @Responsebody (or in your case response body by way of @RestController) and an object is being serialized but has children in a LAZY collection that have not been referenced. By the time you are in your controller there is no longer a transaction active that will facilitate them being fetched (like the one your started in your @Service). You can either make your fetch strategy EAGER, bring in your collections by reference while still in your transaction or make your LAZY collections JSON Transient.

Threeply answered 17/11, 2014 at 0:46 Comment(4)
Okay so @JsonIgnore worked on the un-initialized collection, however now I am getting an error about serialization. Any ideas on my latest stack trace. I updated my question with details.Dampen
This typically happens because a class wanting to be serialized has private fields without public getters and setters. This doesn't seem to be the case here. Also - where is Games? Before we go to a lot of trouble trying to debug this, just for laughs, put @JsonSerialize over the class declaration for ESRBRating. Also, please accept my answer for the first issue.Threeply
If you're using a later Jackson it would be @JsonInclude(Include.NON_NULL)Threeply
I updated my question. JsonInclude and JsonSerialize did not make a difference. Also somehow I got back to my original stack trace which is odd. I did some research and found @Proxy(lazy = false). After I added that to the ESRBRating class it started working fine. However I'm not sure what kind of impact this will have on the application (performance, memory consumption, etc.)Dampen
P
11

First download jackson-datatype-hibernate4-2.2.3.jar or higher version according to jackson-core version. Then use this code in config file and you can use fetch strategy LAZY without any error.

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module;


public class ApplicationConfig extends WebMvcConfigurerAdapter
{
public MappingJackson2HttpMessageConverter jacksonMessageConverter(){
    MappingJackson2HttpMessageConverter messageConverter = new  MappingJackson2HttpMessageConverter();

    ObjectMapper mapper = new ObjectMapper();
    //Registering Hibernate4Module to support lazy objects
    mapper.registerModule(new Hibernate4Module());

    messageConverter.setObjectMapper(mapper);
    return messageConverter;

}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    //Here we add our custom-configured HttpMessageConverter
    converters.add(jacksonMessageConverter());
    super.configureMessageConverters(converters);
}
Periodic answered 27/11, 2015 at 8:20 Comment(0)
O
4

@JsonIgnore annotation might solve your problem, but it causes that particular field that you initially set as FetchType.LAZY to be completely ignored. A better alternative is given here https://mcmap.net/q/89254/-avoid-jackson-serialization-on-non-fetched-lazy-objects

Opsonize answered 12/1, 2016 at 9:45 Comment(0)
K
2

Solved for Spring Boot 2.3.0 by adding to gradle.build:

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5:2.11.3'

And declaring one more bean:

@Bean
public Module datatypeHibernateModule() {
    return new Hibernate5Module();
}
Kaila answered 14/10, 2020 at 21:52 Comment(0)
P
2

I've met the same error, but no answer helped me.

It appeared that the problem was in jpa.open-in-view=false. I've removed it and now everything works as expected.

Prong answered 12/1, 2021 at 16:52 Comment(2)
I added this property and started having the session issue. I removed it and the problem went away. I am wondering why this property has this impact?Disenthral
@smmelzer, #30549989Charybdis
A
1

In my case I just needed to add

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

in my application.properties file

Alphard answered 7/9, 2022 at 8:3 Comment(1)
Found this baeldung.com/hibernate-lazy-loading-workaround, i think i's useful.Severalty

© 2022 - 2024 — McMap. All rights reserved.